Home | History | Annotate | Line # | Download | only in netbt
hci_link.c revision 1.24.26.1
      1  1.24.26.1  pgoyette /*	$NetBSD: hci_link.c,v 1.24.26.1 2018/09/30 01:45:56 pgoyette Exp $	*/
      2        1.1   gdamore 
      3        1.1   gdamore /*-
      4        1.1   gdamore  * Copyright (c) 2005 Iain Hibbert.
      5        1.1   gdamore  * Copyright (c) 2006 Itronix Inc.
      6        1.1   gdamore  * All rights reserved.
      7        1.1   gdamore  *
      8        1.1   gdamore  * Redistribution and use in source and binary forms, with or without
      9        1.1   gdamore  * modification, are permitted provided that the following conditions
     10        1.1   gdamore  * are met:
     11        1.1   gdamore  * 1. Redistributions of source code must retain the above copyright
     12        1.1   gdamore  *    notice, this list of conditions and the following disclaimer.
     13        1.1   gdamore  * 2. Redistributions in binary form must reproduce the above copyright
     14        1.1   gdamore  *    notice, this list of conditions and the following disclaimer in the
     15        1.1   gdamore  *    documentation and/or other materials provided with the distribution.
     16        1.1   gdamore  * 3. The name of Itronix Inc. may not be used to endorse
     17        1.1   gdamore  *    or promote products derived from this software without specific
     18        1.1   gdamore  *    prior written permission.
     19        1.1   gdamore  *
     20        1.1   gdamore  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
     21        1.1   gdamore  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22        1.1   gdamore  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23        1.1   gdamore  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
     24        1.1   gdamore  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     25        1.1   gdamore  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     26        1.1   gdamore  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     27        1.1   gdamore  * ON ANY THEORY OF LIABILITY, WHETHER IN
     28        1.1   gdamore  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29        1.1   gdamore  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30        1.1   gdamore  * POSSIBILITY OF SUCH DAMAGE.
     31        1.1   gdamore  */
     32        1.1   gdamore 
     33        1.1   gdamore #include <sys/cdefs.h>
     34  1.24.26.1  pgoyette __KERNEL_RCSID(0, "$NetBSD: hci_link.c,v 1.24.26.1 2018/09/30 01:45:56 pgoyette Exp $");
     35        1.1   gdamore 
     36        1.1   gdamore #include <sys/param.h>
     37        1.1   gdamore #include <sys/kernel.h>
     38        1.1   gdamore #include <sys/malloc.h>
     39        1.1   gdamore #include <sys/mbuf.h>
     40        1.1   gdamore #include <sys/proc.h>
     41        1.1   gdamore #include <sys/queue.h>
     42        1.1   gdamore #include <sys/systm.h>
     43        1.1   gdamore 
     44        1.1   gdamore #include <netbt/bluetooth.h>
     45        1.1   gdamore #include <netbt/hci.h>
     46        1.2      tron #include <netbt/l2cap.h>
     47        1.1   gdamore #include <netbt/sco.h>
     48        1.1   gdamore 
     49        1.1   gdamore /*******************************************************************************
     50        1.1   gdamore  *
     51        1.1   gdamore  *	HCI ACL Connections
     52        1.1   gdamore  */
     53        1.1   gdamore 
     54        1.1   gdamore /*
     55        1.1   gdamore  * Automatically expire unused ACL connections after this number of
     56        1.1   gdamore  * seconds (if zero, do not expire unused connections) [sysctl]
     57        1.1   gdamore  */
     58        1.1   gdamore int hci_acl_expiry = 10;	/* seconds */
     59        1.1   gdamore 
     60        1.1   gdamore /*
     61        1.1   gdamore  * hci_acl_open(unit, bdaddr)
     62        1.1   gdamore  *
     63        1.1   gdamore  * open ACL connection to remote bdaddr. Only one ACL connection is permitted
     64        1.1   gdamore  * between any two Bluetooth devices, so we look for an existing one before
     65        1.1   gdamore  * trying to start a new one.
     66        1.1   gdamore  */
     67        1.1   gdamore struct hci_link *
     68        1.1   gdamore hci_acl_open(struct hci_unit *unit, bdaddr_t *bdaddr)
     69        1.1   gdamore {
     70        1.1   gdamore 	struct hci_link *link;
     71        1.2      tron 	struct hci_memo *memo;
     72        1.1   gdamore 	hci_create_con_cp cp;
     73        1.1   gdamore 	int err;
     74        1.1   gdamore 
     75       1.10    plunky 	KASSERT(unit != NULL);
     76       1.10    plunky 	KASSERT(bdaddr != NULL);
     77        1.1   gdamore 
     78        1.1   gdamore 	link = hci_link_lookup_bdaddr(unit, bdaddr, HCI_LINK_ACL);
     79        1.1   gdamore 	if (link == NULL) {
     80       1.19    plunky 		link = hci_link_alloc(unit, bdaddr, HCI_LINK_ACL);
     81        1.1   gdamore 		if (link == NULL)
     82        1.1   gdamore 			return NULL;
     83        1.1   gdamore 	}
     84        1.1   gdamore 
     85        1.1   gdamore 	switch(link->hl_state) {
     86        1.1   gdamore 	case HCI_LINK_CLOSED:
     87        1.1   gdamore 		/*
     88        1.1   gdamore 		 * open connection to remote device
     89        1.1   gdamore 		 */
     90        1.1   gdamore 		memset(&cp, 0, sizeof(cp));
     91        1.1   gdamore 		bdaddr_copy(&cp.bdaddr, bdaddr);
     92        1.1   gdamore 		cp.pkt_type = htole16(unit->hci_packet_type);
     93        1.2      tron 
     94        1.2      tron 		memo = hci_memo_find(unit, bdaddr);
     95        1.2      tron 		if (memo != NULL) {
     96       1.13    plunky 			cp.page_scan_rep_mode = memo->page_scan_rep_mode;
     97       1.13    plunky 			cp.page_scan_mode = memo->page_scan_mode;
     98       1.13    plunky 			cp.clock_offset = memo->clock_offset;
     99        1.2      tron 		}
    100        1.2      tron 
    101        1.1   gdamore 		if (unit->hci_link_policy & HCI_LINK_POLICY_ENABLE_ROLE_SWITCH)
    102        1.1   gdamore 			cp.accept_role_switch = 1;
    103        1.1   gdamore 
    104        1.1   gdamore 		err = hci_send_cmd(unit, HCI_CMD_CREATE_CON, &cp, sizeof(cp));
    105        1.1   gdamore 		if (err) {
    106        1.1   gdamore 			hci_link_free(link, err);
    107        1.1   gdamore 			return NULL;
    108        1.1   gdamore 		}
    109        1.1   gdamore 
    110       1.17    plunky 		link->hl_flags |= HCI_LINK_CREATE_CON;
    111        1.1   gdamore 		link->hl_state = HCI_LINK_WAIT_CONNECT;
    112        1.1   gdamore 		break;
    113        1.1   gdamore 
    114        1.1   gdamore 	case HCI_LINK_WAIT_CONNECT:
    115       1.11    plunky 	case HCI_LINK_WAIT_AUTH:
    116       1.11    plunky 	case HCI_LINK_WAIT_ENCRYPT:
    117       1.11    plunky 	case HCI_LINK_WAIT_SECURE:
    118        1.1   gdamore 		/*
    119        1.1   gdamore 		 * somebody else already trying to connect, we just
    120        1.1   gdamore 		 * sit on the bench with them..
    121        1.1   gdamore 		 */
    122        1.1   gdamore 		break;
    123        1.1   gdamore 
    124        1.1   gdamore 	case HCI_LINK_OPEN:
    125        1.1   gdamore 		/*
    126        1.1   gdamore 		 * If already open, halt any expiry timeouts. We dont need
    127        1.1   gdamore 		 * to care about already invoking timeouts since refcnt >0
    128        1.1   gdamore 		 * will keep the link alive.
    129        1.1   gdamore 		 */
    130        1.1   gdamore 		callout_stop(&link->hl_expire);
    131        1.1   gdamore 		break;
    132        1.1   gdamore 
    133        1.1   gdamore 	default:
    134        1.1   gdamore 		UNKNOWN(link->hl_state);
    135        1.1   gdamore 		return NULL;
    136        1.1   gdamore 	}
    137        1.1   gdamore 
    138        1.1   gdamore 	/* open */
    139        1.1   gdamore 	link->hl_refcnt++;
    140        1.1   gdamore 
    141        1.1   gdamore 	return link;
    142        1.1   gdamore }
    143        1.1   gdamore 
    144        1.1   gdamore /*
    145        1.1   gdamore  * Close ACL connection. When there are no more references to this link,
    146        1.1   gdamore  * we can either close it down or schedule a delayed closedown.
    147        1.1   gdamore  */
    148        1.1   gdamore void
    149        1.1   gdamore hci_acl_close(struct hci_link *link, int err)
    150        1.1   gdamore {
    151        1.1   gdamore 
    152       1.10    plunky 	KASSERT(link != NULL);
    153        1.1   gdamore 
    154        1.1   gdamore 	if (--link->hl_refcnt == 0) {
    155        1.1   gdamore 		if (link->hl_state == HCI_LINK_CLOSED)
    156        1.1   gdamore 			hci_link_free(link, err);
    157        1.1   gdamore 		else if (hci_acl_expiry > 0)
    158        1.1   gdamore 			callout_schedule(&link->hl_expire, hci_acl_expiry * hz);
    159        1.1   gdamore 	}
    160        1.1   gdamore }
    161        1.1   gdamore 
    162        1.1   gdamore /*
    163        1.3      tron  * Incoming ACL connection.
    164        1.3      tron  *
    165       1.21    plunky  * Check the L2CAP listeners list and only accept when there is a
    166       1.21    plunky  * potential listener available.
    167        1.3      tron  *
    168        1.3      tron  * There should not be a link to the same bdaddr already, we check
    169        1.3      tron  * anyway though its left unhandled for now.
    170        1.1   gdamore  */
    171        1.1   gdamore struct hci_link *
    172        1.1   gdamore hci_acl_newconn(struct hci_unit *unit, bdaddr_t *bdaddr)
    173        1.1   gdamore {
    174        1.1   gdamore 	struct hci_link *link;
    175       1.21    plunky 	struct l2cap_channel *chan;
    176       1.21    plunky 
    177       1.21    plunky 	LIST_FOREACH(chan, &l2cap_listen_list, lc_ncid) {
    178       1.21    plunky 		if (bdaddr_same(&unit->hci_bdaddr, &chan->lc_laddr.bt_bdaddr)
    179       1.21    plunky 		    || bdaddr_any(&chan->lc_laddr.bt_bdaddr))
    180       1.21    plunky 			break;
    181       1.21    plunky 	}
    182       1.21    plunky 
    183       1.21    plunky 	if (chan == NULL) {
    184       1.21    plunky 		DPRINTF("%s: rejecting connection (no listeners)\n",
    185       1.21    plunky 		    device_xname(unit->hci_dev));
    186       1.21    plunky 
    187       1.21    plunky 		return NULL;
    188       1.21    plunky 	}
    189        1.1   gdamore 
    190        1.3      tron 	link = hci_link_lookup_bdaddr(unit, bdaddr, HCI_LINK_ACL);
    191       1.21    plunky 	if (link != NULL) {
    192       1.21    plunky 		DPRINTF("%s: rejecting connection (link exists)\n",
    193       1.21    plunky 		    device_xname(unit->hci_dev));
    194       1.21    plunky 
    195        1.3      tron 		return NULL;
    196       1.21    plunky 	}
    197        1.3      tron 
    198       1.19    plunky 	link = hci_link_alloc(unit, bdaddr, HCI_LINK_ACL);
    199        1.1   gdamore 	if (link != NULL) {
    200        1.1   gdamore 		link->hl_state = HCI_LINK_WAIT_CONNECT;
    201        1.1   gdamore 
    202        1.1   gdamore 		if (hci_acl_expiry > 0)
    203        1.1   gdamore 			callout_schedule(&link->hl_expire, hci_acl_expiry * hz);
    204        1.1   gdamore 	}
    205        1.1   gdamore 
    206        1.1   gdamore 	return link;
    207        1.1   gdamore }
    208        1.1   gdamore 
    209        1.1   gdamore void
    210        1.1   gdamore hci_acl_timeout(void *arg)
    211        1.1   gdamore {
    212        1.1   gdamore 	struct hci_link *link = arg;
    213        1.1   gdamore 	hci_discon_cp cp;
    214       1.20        ad 	int err;
    215        1.1   gdamore 
    216       1.20        ad 	mutex_enter(bt_lock);
    217        1.1   gdamore 	callout_ack(&link->hl_expire);
    218        1.1   gdamore 
    219        1.1   gdamore 	if (link->hl_refcnt > 0)
    220        1.1   gdamore 		goto out;
    221        1.1   gdamore 
    222        1.1   gdamore 	DPRINTF("link #%d expired\n", link->hl_handle);
    223        1.1   gdamore 
    224        1.1   gdamore 	switch (link->hl_state) {
    225        1.1   gdamore 	case HCI_LINK_CLOSED:
    226        1.1   gdamore 	case HCI_LINK_WAIT_CONNECT:
    227        1.1   gdamore 		hci_link_free(link, ECONNRESET);
    228        1.1   gdamore 		break;
    229        1.1   gdamore 
    230       1.11    plunky 	case HCI_LINK_WAIT_AUTH:
    231       1.11    plunky 	case HCI_LINK_WAIT_ENCRYPT:
    232       1.11    plunky 	case HCI_LINK_WAIT_SECURE:
    233        1.1   gdamore 	case HCI_LINK_OPEN:
    234        1.1   gdamore 		cp.con_handle = htole16(link->hl_handle);
    235        1.1   gdamore 		cp.reason = 0x13; /* "Remote User Terminated Connection" */
    236        1.1   gdamore 
    237        1.1   gdamore 		err = hci_send_cmd(link->hl_unit, HCI_CMD_DISCONNECT,
    238        1.1   gdamore 					&cp, sizeof(cp));
    239        1.1   gdamore 
    240        1.6  christos 		if (err) {
    241        1.1   gdamore 			DPRINTF("error %d sending HCI_CMD_DISCONNECT\n",
    242        1.6  christos 			    err);
    243        1.6  christos 		}
    244        1.1   gdamore 
    245        1.1   gdamore 		break;
    246        1.1   gdamore 
    247        1.1   gdamore 	default:
    248        1.1   gdamore 		UNKNOWN(link->hl_state);
    249        1.1   gdamore 		break;
    250        1.1   gdamore 	}
    251        1.1   gdamore 
    252        1.1   gdamore out:
    253       1.20        ad 	mutex_exit(bt_lock);
    254        1.1   gdamore }
    255        1.1   gdamore 
    256        1.1   gdamore /*
    257       1.11    plunky  * Initiate any Link Mode change requests.
    258       1.11    plunky  */
    259       1.11    plunky int
    260       1.11    plunky hci_acl_setmode(struct hci_link *link)
    261       1.11    plunky {
    262       1.11    plunky 	int err;
    263       1.11    plunky 
    264       1.11    plunky 	KASSERT(link != NULL);
    265       1.11    plunky 	KASSERT(link->hl_unit != NULL);
    266       1.11    plunky 
    267       1.11    plunky 	if (link->hl_state != HCI_LINK_OPEN)
    268       1.11    plunky 		return EINPROGRESS;
    269       1.11    plunky 
    270       1.11    plunky 	if ((link->hl_flags & HCI_LINK_AUTH_REQ)
    271       1.11    plunky 	    && !(link->hl_flags & HCI_LINK_AUTH)) {
    272       1.11    plunky 		hci_auth_req_cp cp;
    273       1.11    plunky 
    274       1.11    plunky 		DPRINTF("requesting auth for handle #%d\n",
    275       1.11    plunky 			link->hl_handle);
    276       1.11    plunky 
    277       1.11    plunky 		link->hl_state = HCI_LINK_WAIT_AUTH;
    278       1.11    plunky 		cp.con_handle = htole16(link->hl_handle);
    279       1.11    plunky 		err = hci_send_cmd(link->hl_unit, HCI_CMD_AUTH_REQ,
    280       1.11    plunky 				   &cp, sizeof(cp));
    281       1.11    plunky 
    282       1.11    plunky 		return (err == 0 ? EINPROGRESS : err);
    283       1.11    plunky 	}
    284       1.11    plunky 
    285       1.11    plunky 	if ((link->hl_flags & HCI_LINK_ENCRYPT_REQ)
    286       1.11    plunky 	    && !(link->hl_flags & HCI_LINK_ENCRYPT)) {
    287       1.11    plunky 		hci_set_con_encryption_cp cp;
    288       1.11    plunky 
    289       1.11    plunky 		/* XXX we should check features for encryption capability */
    290       1.11    plunky 
    291       1.11    plunky 		DPRINTF("requesting encryption for handle #%d\n",
    292       1.11    plunky 			link->hl_handle);
    293       1.11    plunky 
    294       1.11    plunky 		link->hl_state = HCI_LINK_WAIT_ENCRYPT;
    295       1.11    plunky 		cp.con_handle = htole16(link->hl_handle);
    296       1.11    plunky 		cp.encryption_enable = 0x01;
    297       1.11    plunky 
    298       1.11    plunky 		err = hci_send_cmd(link->hl_unit, HCI_CMD_SET_CON_ENCRYPTION,
    299       1.11    plunky 				   &cp, sizeof(cp));
    300       1.11    plunky 
    301       1.11    plunky 		return (err == 0 ? EINPROGRESS : err);
    302       1.11    plunky 	}
    303       1.11    plunky 
    304       1.11    plunky 	if ((link->hl_flags & HCI_LINK_SECURE_REQ)) {
    305       1.11    plunky 		hci_change_con_link_key_cp cp;
    306       1.11    plunky 
    307       1.11    plunky 		/* always change link key for SECURE requests */
    308       1.11    plunky 		link->hl_flags &= ~HCI_LINK_SECURE;
    309       1.11    plunky 
    310       1.11    plunky 		DPRINTF("changing link key for handle #%d\n",
    311       1.11    plunky 			link->hl_handle);
    312       1.11    plunky 
    313       1.11    plunky 		link->hl_state = HCI_LINK_WAIT_SECURE;
    314       1.11    plunky 		cp.con_handle = htole16(link->hl_handle);
    315       1.11    plunky 
    316       1.11    plunky 		err = hci_send_cmd(link->hl_unit, HCI_CMD_CHANGE_CON_LINK_KEY,
    317       1.11    plunky 				   &cp, sizeof(cp));
    318       1.11    plunky 
    319       1.11    plunky 		return (err == 0 ? EINPROGRESS : err);
    320       1.11    plunky 	}
    321       1.11    plunky 
    322       1.11    plunky 	return 0;
    323       1.11    plunky }
    324       1.11    plunky 
    325       1.11    plunky /*
    326       1.11    plunky  * Link Mode changed.
    327       1.11    plunky  *
    328       1.11    plunky  * This is called from event handlers when the mode change
    329       1.11    plunky  * is complete. We notify upstream and restart the link.
    330       1.11    plunky  */
    331       1.11    plunky void
    332       1.11    plunky hci_acl_linkmode(struct hci_link *link)
    333       1.11    plunky {
    334       1.11    plunky 	struct l2cap_channel *chan, *next;
    335       1.11    plunky 	int err, mode = 0;
    336       1.11    plunky 
    337       1.11    plunky 	DPRINTF("handle #%d, auth %s, encrypt %s, secure %s\n",
    338       1.11    plunky 		link->hl_handle,
    339       1.11    plunky 		(link->hl_flags & HCI_LINK_AUTH ? "on" : "off"),
    340       1.11    plunky 		(link->hl_flags & HCI_LINK_ENCRYPT ? "on" : "off"),
    341       1.11    plunky 		(link->hl_flags & HCI_LINK_SECURE ? "on" : "off"));
    342       1.11    plunky 
    343       1.11    plunky 	if (link->hl_flags & HCI_LINK_AUTH)
    344       1.11    plunky 		mode |= L2CAP_LM_AUTH;
    345       1.11    plunky 
    346       1.11    plunky 	if (link->hl_flags & HCI_LINK_ENCRYPT)
    347       1.11    plunky 		mode |= L2CAP_LM_ENCRYPT;
    348       1.11    plunky 
    349       1.11    plunky 	if (link->hl_flags & HCI_LINK_SECURE)
    350       1.11    plunky 		mode |= L2CAP_LM_SECURE;
    351       1.11    plunky 
    352       1.11    plunky 	/*
    353       1.11    plunky 	 * The link state will only be OPEN here if the mode change
    354       1.11    plunky 	 * was successful. So, we can proceed with L2CAP connections,
    355       1.11    plunky 	 * or notify already establshed channels, to allow any that
    356       1.11    plunky 	 * are dissatisfied to disconnect before we restart.
    357       1.11    plunky 	 */
    358       1.11    plunky 	next = LIST_FIRST(&l2cap_active_list);
    359       1.11    plunky 	while ((chan = next) != NULL) {
    360       1.11    plunky 		next = LIST_NEXT(chan, lc_ncid);
    361       1.11    plunky 
    362       1.11    plunky 		if (chan->lc_link != link)
    363       1.11    plunky 			continue;
    364       1.11    plunky 
    365       1.11    plunky 		switch(chan->lc_state) {
    366       1.11    plunky 		case L2CAP_WAIT_SEND_CONNECT_REQ: /* we are connecting */
    367       1.11    plunky 			if ((mode & chan->lc_mode) != chan->lc_mode) {
    368       1.11    plunky 				l2cap_close(chan, ECONNABORTED);
    369       1.11    plunky 				break;
    370       1.11    plunky 			}
    371       1.11    plunky 
    372       1.11    plunky 			chan->lc_state = L2CAP_WAIT_RECV_CONNECT_RSP;
    373       1.11    plunky 			err = l2cap_send_connect_req(chan);
    374       1.11    plunky 			if (err) {
    375       1.11    plunky 				l2cap_close(chan, err);
    376       1.11    plunky 				break;
    377       1.11    plunky 			}
    378       1.11    plunky 			break;
    379       1.11    plunky 
    380       1.11    plunky 		case L2CAP_WAIT_SEND_CONNECT_RSP: /* they are connecting */
    381       1.11    plunky 			if ((mode & chan->lc_mode) != chan->lc_mode) {
    382       1.11    plunky 				l2cap_send_connect_rsp(link, chan->lc_ident,
    383       1.11    plunky 							0, chan->lc_rcid,
    384       1.11    plunky 							L2CAP_SECURITY_BLOCK);
    385       1.11    plunky 
    386       1.11    plunky 				l2cap_close(chan, ECONNABORTED);
    387       1.11    plunky 				break;
    388       1.11    plunky 			}
    389       1.11    plunky 
    390       1.11    plunky 			l2cap_send_connect_rsp(link, chan->lc_ident,
    391       1.11    plunky 						chan->lc_lcid, chan->lc_rcid,
    392       1.11    plunky 						L2CAP_SUCCESS);
    393       1.11    plunky 
    394       1.11    plunky 			chan->lc_state = L2CAP_WAIT_CONFIG;
    395       1.11    plunky 			chan->lc_flags |= (L2CAP_WAIT_CONFIG_RSP | L2CAP_WAIT_CONFIG_REQ);
    396       1.11    plunky 			err = l2cap_send_config_req(chan);
    397       1.11    plunky 			if (err) {
    398       1.11    plunky 				l2cap_close(chan, err);
    399       1.11    plunky 				break;
    400       1.11    plunky 			}
    401       1.11    plunky 			break;
    402       1.11    plunky 
    403       1.11    plunky 		case L2CAP_WAIT_RECV_CONNECT_RSP:
    404       1.11    plunky 		case L2CAP_WAIT_CONFIG:
    405       1.11    plunky 		case L2CAP_OPEN: /* already established */
    406       1.11    plunky 			(*chan->lc_proto->linkmode)(chan->lc_upper, mode);
    407       1.11    plunky 			break;
    408       1.11    plunky 
    409       1.11    plunky 		default:
    410       1.11    plunky 			break;
    411       1.11    plunky 		}
    412       1.11    plunky 	}
    413       1.11    plunky 
    414       1.11    plunky 	link->hl_state = HCI_LINK_OPEN;
    415       1.11    plunky 	hci_acl_start(link);
    416       1.11    plunky }
    417       1.11    plunky 
    418       1.11    plunky /*
    419        1.1   gdamore  * Receive ACL Data
    420        1.1   gdamore  *
    421        1.1   gdamore  * we accumulate packet fragments on the hci_link structure
    422        1.1   gdamore  * until a full L2CAP frame is ready, then send it on.
    423        1.1   gdamore  */
    424        1.1   gdamore void
    425        1.1   gdamore hci_acl_recv(struct mbuf *m, struct hci_unit *unit)
    426        1.1   gdamore {
    427        1.1   gdamore 	struct hci_link *link;
    428        1.1   gdamore 	hci_acldata_hdr_t hdr;
    429        1.1   gdamore 	uint16_t handle, want;
    430        1.1   gdamore 	int pb, got;
    431        1.1   gdamore 
    432       1.10    plunky 	KASSERT(m != NULL);
    433       1.10    plunky 	KASSERT(unit != NULL);
    434        1.1   gdamore 
    435       1.23    plunky 	if (m->m_pkthdr.len < sizeof(hdr))
    436       1.23    plunky 		goto bad;
    437       1.23    plunky 
    438        1.1   gdamore 	m_copydata(m, 0, sizeof(hdr), &hdr);
    439        1.1   gdamore 	m_adj(m, sizeof(hdr));
    440        1.1   gdamore 
    441       1.23    plunky 	KASSERT(hdr.type == HCI_ACL_DATA_PKT);
    442        1.1   gdamore 
    443        1.1   gdamore 	hdr.length = le16toh(hdr.length);
    444        1.1   gdamore 	hdr.con_handle = le16toh(hdr.con_handle);
    445        1.1   gdamore 	handle = HCI_CON_HANDLE(hdr.con_handle);
    446        1.1   gdamore 	pb = HCI_PB_FLAG(hdr.con_handle);
    447        1.1   gdamore 
    448       1.23    plunky 	if (m->m_pkthdr.len != hdr.length)
    449       1.23    plunky 		goto bad;
    450       1.23    plunky 
    451        1.1   gdamore 	link = hci_link_lookup_handle(unit, handle);
    452        1.1   gdamore 	if (link == NULL) {
    453        1.1   gdamore 		hci_discon_cp cp;
    454        1.1   gdamore 
    455        1.1   gdamore 		DPRINTF("%s: dumping packet for unknown handle #%d\n",
    456       1.16    plunky 			device_xname(unit->hci_dev), handle);
    457        1.1   gdamore 
    458        1.1   gdamore 		/*
    459        1.1   gdamore 		 * There is no way to find out what this connection handle is
    460        1.1   gdamore 		 * for, just get rid of it. This may happen, if a USB dongle
    461        1.1   gdamore 		 * is plugged into a self powered hub and does not reset when
    462        1.1   gdamore 		 * the system is shut down.
    463       1.22    plunky 		 *
    464       1.22    plunky 		 * This can cause a problem with some Broadcom controllers
    465       1.22    plunky 		 * which emit empty ACL packets during connection setup, so
    466       1.22    plunky 		 * only disconnect where data is present.
    467        1.1   gdamore 		 */
    468       1.22    plunky 		if (hdr.length > 0) {
    469       1.22    plunky 			cp.con_handle = htole16(handle);
    470       1.22    plunky 			cp.reason = 0x13;/*"Remote User Terminated Connection"*/
    471       1.22    plunky 			hci_send_cmd(unit, HCI_CMD_DISCONNECT, &cp, sizeof(cp));
    472       1.22    plunky 		}
    473        1.1   gdamore 		goto bad;
    474        1.1   gdamore 	}
    475        1.1   gdamore 
    476        1.1   gdamore 	switch (pb) {
    477        1.1   gdamore 	case HCI_PACKET_START:
    478  1.24.26.1  pgoyette 		if (m->m_pkthdr.len < sizeof(l2cap_hdr_t))
    479  1.24.26.1  pgoyette 			goto bad;
    480  1.24.26.1  pgoyette 
    481  1.24.26.1  pgoyette 		if (link->hl_rxp != NULL) {
    482       1.16    plunky 			aprint_error_dev(unit->hci_dev,
    483       1.16    plunky 			    "dropped incomplete ACL packet\n");
    484        1.1   gdamore 
    485  1.24.26.1  pgoyette 			m_freem(link->hl_rxp);
    486  1.24.26.1  pgoyette 		}
    487        1.1   gdamore 
    488        1.1   gdamore 		link->hl_rxp = m;
    489        1.1   gdamore 		got = m->m_pkthdr.len;
    490        1.1   gdamore 		break;
    491        1.1   gdamore 
    492        1.1   gdamore 	case HCI_PACKET_FRAGMENT:
    493        1.1   gdamore 		if (link->hl_rxp == NULL) {
    494       1.16    plunky 			aprint_error_dev(unit->hci_dev,
    495       1.16    plunky 			    "unexpected packet fragment\n");
    496        1.1   gdamore 
    497        1.1   gdamore 			goto bad;
    498        1.1   gdamore 		}
    499        1.1   gdamore 
    500        1.1   gdamore 		got = m->m_pkthdr.len + link->hl_rxp->m_pkthdr.len;
    501        1.1   gdamore 		m_cat(link->hl_rxp, m);
    502        1.1   gdamore 		m = link->hl_rxp;
    503        1.1   gdamore 		m->m_pkthdr.len = got;
    504        1.1   gdamore 		break;
    505        1.1   gdamore 
    506        1.1   gdamore 	default:
    507       1.23    plunky 		DPRINTF("%s: unknown packet type\n",
    508       1.23    plunky 		    device_xname(unit->hci_dev));
    509       1.23    plunky 
    510        1.1   gdamore 		goto bad;
    511        1.1   gdamore 	}
    512        1.1   gdamore 
    513        1.1   gdamore 	m_copydata(m, 0, sizeof(want), &want);
    514  1.24.26.1  pgoyette 	want = le16toh(want);
    515  1.24.26.1  pgoyette 	got -= sizeof(l2cap_hdr_t);
    516        1.1   gdamore 
    517  1.24.26.1  pgoyette 	if (got < want)		/* wait for more */
    518        1.1   gdamore 		return;
    519        1.1   gdamore 
    520        1.1   gdamore 	link->hl_rxp = NULL;
    521        1.1   gdamore 
    522  1.24.26.1  pgoyette 	if (got > want) {
    523  1.24.26.1  pgoyette 		DPRINTF("%s: packet overflow\n",
    524  1.24.26.1  pgoyette 			device_xname(unit->hci_dev));
    525  1.24.26.1  pgoyette 
    526  1.24.26.1  pgoyette 		goto bad;
    527        1.1   gdamore 	}
    528        1.1   gdamore 
    529  1.24.26.1  pgoyette 	l2cap_recv_frame(m, link);
    530  1.24.26.1  pgoyette 	return;
    531  1.24.26.1  pgoyette 
    532        1.1   gdamore bad:
    533        1.1   gdamore 	m_freem(m);
    534        1.1   gdamore }
    535        1.1   gdamore 
    536        1.1   gdamore /*
    537        1.1   gdamore  * Send ACL data on link
    538        1.1   gdamore  *
    539        1.1   gdamore  * We must fragment packets into chunks of less than unit->hci_max_acl_size and
    540        1.1   gdamore  * prepend a relevant ACL header to each fragment. We keep a PDU structure
    541        1.1   gdamore  * attached to the link, so that completed fragments can be marked off and
    542        1.1   gdamore  * more data requested from above once the PDU is sent.
    543        1.1   gdamore  */
    544        1.1   gdamore int
    545        1.1   gdamore hci_acl_send(struct mbuf *m, struct hci_link *link,
    546        1.1   gdamore 		struct l2cap_channel *chan)
    547        1.1   gdamore {
    548        1.1   gdamore 	struct l2cap_pdu *pdu;
    549        1.1   gdamore 	struct mbuf *n = NULL;
    550        1.1   gdamore 	int plen, mlen, num = 0;
    551        1.1   gdamore 
    552       1.10    plunky 	KASSERT(link != NULL);
    553       1.10    plunky 	KASSERT(m != NULL);
    554        1.1   gdamore 	KASSERT(m->m_flags & M_PKTHDR);
    555        1.1   gdamore 	KASSERT(m->m_pkthdr.len > 0);
    556        1.1   gdamore 
    557        1.1   gdamore 	if (link->hl_state == HCI_LINK_CLOSED) {
    558        1.1   gdamore 		m_freem(m);
    559        1.1   gdamore 		return ENETDOWN;
    560        1.1   gdamore 	}
    561        1.1   gdamore 
    562        1.1   gdamore 	pdu = pool_get(&l2cap_pdu_pool, PR_NOWAIT);
    563        1.1   gdamore 	if (pdu == NULL)
    564        1.1   gdamore 		goto nomem;
    565        1.1   gdamore 
    566        1.1   gdamore 	pdu->lp_chan = chan;
    567        1.1   gdamore 	pdu->lp_pending = 0;
    568        1.1   gdamore 	MBUFQ_INIT(&pdu->lp_data);
    569        1.1   gdamore 
    570        1.1   gdamore 	plen = m->m_pkthdr.len;
    571        1.1   gdamore 	mlen = link->hl_unit->hci_max_acl_size;
    572        1.1   gdamore 
    573        1.1   gdamore 	DPRINTFN(5, "%s: handle #%d, plen = %d, max = %d\n",
    574       1.16    plunky 		device_xname(link->hl_unit->hci_dev), link->hl_handle, plen, mlen);
    575        1.1   gdamore 
    576        1.1   gdamore 	while (plen > 0) {
    577        1.1   gdamore 		if (plen > mlen) {
    578        1.1   gdamore 			n = m_split(m, mlen, M_DONTWAIT);
    579        1.1   gdamore 			if (n == NULL)
    580        1.1   gdamore 				goto nomem;
    581        1.1   gdamore 		} else {
    582        1.1   gdamore 			mlen = plen;
    583        1.1   gdamore 		}
    584        1.1   gdamore 
    585        1.1   gdamore 		if (num++ == 0)
    586        1.1   gdamore 			m->m_flags |= M_PROTO1;	/* tag first fragment */
    587        1.1   gdamore 
    588        1.1   gdamore 		DPRINTFN(10, "chunk of %d (plen = %d) bytes\n", mlen, plen);
    589        1.1   gdamore 		MBUFQ_ENQUEUE(&pdu->lp_data, m);
    590        1.1   gdamore 		m = n;
    591        1.1   gdamore 		plen -= mlen;
    592        1.1   gdamore 	}
    593        1.1   gdamore 
    594        1.1   gdamore 	TAILQ_INSERT_TAIL(&link->hl_txq, pdu, lp_next);
    595        1.1   gdamore 	link->hl_txqlen += num;
    596        1.1   gdamore 
    597        1.1   gdamore 	hci_acl_start(link);
    598        1.1   gdamore 
    599        1.1   gdamore 	return 0;
    600        1.1   gdamore 
    601        1.1   gdamore nomem:
    602        1.1   gdamore 	if (m) m_freem(m);
    603        1.1   gdamore 	if (pdu) {
    604        1.1   gdamore 		MBUFQ_DRAIN(&pdu->lp_data);
    605        1.1   gdamore 		pool_put(&l2cap_pdu_pool, pdu);
    606        1.1   gdamore 	}
    607        1.1   gdamore 
    608        1.1   gdamore 	return ENOMEM;
    609        1.1   gdamore }
    610        1.1   gdamore 
    611        1.1   gdamore /*
    612        1.1   gdamore  * Start sending ACL data on link.
    613        1.1   gdamore  *
    614       1.11    plunky  *	This is called when the queue may need restarting: as new data
    615       1.11    plunky  * is queued, after link mode changes have completed, or when device
    616       1.11    plunky  * buffers have cleared.
    617       1.11    plunky  *
    618        1.1   gdamore  *	We may use all the available packet slots. The reason that we add
    619        1.1   gdamore  * the ACL encapsulation here rather than in hci_acl_send() is that L2CAP
    620        1.1   gdamore  * signal packets may be queued before the handle is given to us..
    621        1.1   gdamore  */
    622        1.1   gdamore void
    623        1.1   gdamore hci_acl_start(struct hci_link *link)
    624        1.1   gdamore {
    625        1.1   gdamore 	struct hci_unit *unit;
    626        1.1   gdamore 	hci_acldata_hdr_t *hdr;
    627        1.1   gdamore 	struct l2cap_pdu *pdu;
    628        1.1   gdamore 	struct mbuf *m;
    629        1.1   gdamore 	uint16_t handle;
    630        1.1   gdamore 
    631       1.10    plunky 	KASSERT(link != NULL);
    632        1.1   gdamore 
    633        1.1   gdamore 	unit = link->hl_unit;
    634       1.10    plunky 	KASSERT(unit != NULL);
    635        1.1   gdamore 
    636        1.1   gdamore 	/* this is mainly to block ourselves (below) */
    637        1.1   gdamore 	if (link->hl_state != HCI_LINK_OPEN)
    638        1.1   gdamore 		return;
    639        1.1   gdamore 
    640        1.1   gdamore 	if (link->hl_txqlen == 0 || unit->hci_num_acl_pkts == 0)
    641        1.1   gdamore 		return;
    642        1.1   gdamore 
    643        1.1   gdamore 	/* find first PDU with data to send */
    644        1.1   gdamore 	pdu = TAILQ_FIRST(&link->hl_txq);
    645        1.1   gdamore 	for (;;) {
    646        1.1   gdamore 		if (pdu == NULL)
    647        1.1   gdamore 			return;
    648        1.1   gdamore 
    649        1.1   gdamore 		if (MBUFQ_FIRST(&pdu->lp_data) != NULL)
    650        1.1   gdamore 			break;
    651        1.1   gdamore 
    652        1.1   gdamore 		pdu = TAILQ_NEXT(pdu, lp_next);
    653        1.1   gdamore 	}
    654        1.1   gdamore 
    655        1.1   gdamore 	while (unit->hci_num_acl_pkts > 0) {
    656        1.1   gdamore 		MBUFQ_DEQUEUE(&pdu->lp_data, m);
    657        1.1   gdamore 		KASSERT(m != NULL);
    658        1.1   gdamore 
    659        1.1   gdamore 		if (m->m_flags & M_PROTO1)
    660        1.1   gdamore 			handle = HCI_MK_CON_HANDLE(link->hl_handle,
    661        1.1   gdamore 						HCI_PACKET_START, 0);
    662        1.1   gdamore 		else
    663        1.1   gdamore 			handle = HCI_MK_CON_HANDLE(link->hl_handle,
    664        1.1   gdamore 						HCI_PACKET_FRAGMENT, 0);
    665        1.1   gdamore 
    666        1.1   gdamore 		M_PREPEND(m, sizeof(*hdr), M_DONTWAIT);
    667        1.1   gdamore 		if (m == NULL)
    668        1.1   gdamore 			break;
    669        1.1   gdamore 
    670        1.1   gdamore 		hdr = mtod(m, hci_acldata_hdr_t *);
    671        1.1   gdamore 		hdr->type = HCI_ACL_DATA_PKT;
    672        1.1   gdamore 		hdr->con_handle = htole16(handle);
    673        1.1   gdamore 		hdr->length = htole16(m->m_pkthdr.len - sizeof(*hdr));
    674        1.1   gdamore 
    675        1.1   gdamore 		link->hl_txqlen--;
    676        1.1   gdamore 		pdu->lp_pending++;
    677        1.1   gdamore 
    678        1.1   gdamore 		hci_output_acl(unit, m);
    679        1.1   gdamore 
    680        1.1   gdamore 		if (MBUFQ_FIRST(&pdu->lp_data) == NULL) {
    681        1.1   gdamore 			if (pdu->lp_chan) {
    682        1.1   gdamore 				/*
    683        1.1   gdamore 				 * This should enable streaming of PDUs - when
    684        1.1   gdamore 				 * we have placed all the fragments on the acl
    685        1.1   gdamore 				 * output queue, we trigger the L2CAP layer to
    686        1.1   gdamore 				 * send us down one more. Use a false state so
    687        1.1   gdamore 				 * we dont run into ourselves coming back from
    688        1.1   gdamore 				 * the future..
    689        1.1   gdamore 				 */
    690        1.1   gdamore 				link->hl_state = HCI_LINK_BLOCK;
    691        1.1   gdamore 				l2cap_start(pdu->lp_chan);
    692        1.1   gdamore 				link->hl_state = HCI_LINK_OPEN;
    693        1.1   gdamore 			}
    694        1.1   gdamore 
    695        1.1   gdamore 			pdu = TAILQ_NEXT(pdu, lp_next);
    696        1.1   gdamore 			if (pdu == NULL)
    697        1.1   gdamore 				break;
    698        1.1   gdamore 		}
    699        1.1   gdamore 	}
    700        1.1   gdamore 
    701        1.1   gdamore 	/*
    702        1.1   gdamore 	 * We had our turn now, move to the back of the queue to let
    703        1.1   gdamore 	 * other links have a go at the output buffers..
    704        1.1   gdamore 	 */
    705        1.1   gdamore 	if (TAILQ_NEXT(link, hl_next)) {
    706        1.1   gdamore 		TAILQ_REMOVE(&unit->hci_links, link, hl_next);
    707        1.1   gdamore 		TAILQ_INSERT_TAIL(&unit->hci_links, link, hl_next);
    708        1.1   gdamore 	}
    709        1.1   gdamore }
    710        1.1   gdamore 
    711        1.1   gdamore /*
    712        1.1   gdamore  * Confirm ACL packets cleared from Controller buffers. We scan our PDU
    713        1.1   gdamore  * list to clear pending fragments and signal upstream for more data
    714        1.1   gdamore  * when a PDU is complete.
    715        1.1   gdamore  */
    716        1.1   gdamore void
    717        1.1   gdamore hci_acl_complete(struct hci_link *link, int num)
    718        1.1   gdamore {
    719        1.1   gdamore 	struct l2cap_pdu *pdu;
    720        1.1   gdamore 	struct l2cap_channel *chan;
    721        1.1   gdamore 
    722        1.1   gdamore 	DPRINTFN(5, "handle #%d (%d)\n", link->hl_handle, num);
    723        1.1   gdamore 
    724        1.1   gdamore 	while (num > 0) {
    725        1.1   gdamore 		pdu = TAILQ_FIRST(&link->hl_txq);
    726        1.1   gdamore 		if (pdu == NULL) {
    727       1.16    plunky 			aprint_error_dev(link->hl_unit->hci_dev,
    728       1.16    plunky 			    "%d packets completed on handle #%x but none pending!\n",
    729       1.16    plunky 			    num, link->hl_handle);
    730       1.16    plunky 
    731        1.1   gdamore 			return;
    732        1.1   gdamore 		}
    733        1.1   gdamore 
    734        1.1   gdamore 		if (num >= pdu->lp_pending) {
    735        1.1   gdamore 			num -= pdu->lp_pending;
    736        1.1   gdamore 			pdu->lp_pending = 0;
    737        1.1   gdamore 
    738        1.1   gdamore 			if (MBUFQ_FIRST(&pdu->lp_data) == NULL) {
    739        1.1   gdamore 				TAILQ_REMOVE(&link->hl_txq, pdu, lp_next);
    740        1.1   gdamore 				chan = pdu->lp_chan;
    741        1.1   gdamore 				if (chan != NULL) {
    742        1.1   gdamore 					chan->lc_pending--;
    743        1.1   gdamore 					(*chan->lc_proto->complete)
    744        1.1   gdamore 							(chan->lc_upper, 1);
    745        1.1   gdamore 
    746        1.1   gdamore 					if (chan->lc_pending == 0)
    747        1.1   gdamore 						l2cap_start(chan);
    748        1.1   gdamore 				}
    749        1.1   gdamore 
    750        1.1   gdamore 				pool_put(&l2cap_pdu_pool, pdu);
    751        1.1   gdamore 			}
    752        1.1   gdamore 		} else {
    753        1.1   gdamore 			pdu->lp_pending -= num;
    754        1.1   gdamore 			num = 0;
    755        1.1   gdamore 		}
    756        1.1   gdamore 	}
    757        1.1   gdamore }
    758        1.1   gdamore 
    759        1.1   gdamore /*******************************************************************************
    760        1.1   gdamore  *
    761        1.1   gdamore  *	HCI SCO Connections
    762        1.1   gdamore  */
    763        1.1   gdamore 
    764        1.1   gdamore /*
    765        1.3      tron  * Incoming SCO Connection. We check the list for anybody willing
    766        1.3      tron  * to take it.
    767        1.1   gdamore  */
    768        1.1   gdamore struct hci_link *
    769        1.1   gdamore hci_sco_newconn(struct hci_unit *unit, bdaddr_t *bdaddr)
    770        1.1   gdamore {
    771        1.3      tron 	struct sockaddr_bt laddr, raddr;
    772        1.3      tron 	struct sco_pcb *pcb, *new;
    773        1.3      tron 	struct hci_link *sco, *acl;
    774        1.3      tron 
    775        1.3      tron 	memset(&laddr, 0, sizeof(laddr));
    776        1.3      tron 	laddr.bt_len = sizeof(laddr);
    777        1.3      tron 	laddr.bt_family = AF_BLUETOOTH;
    778        1.3      tron 	bdaddr_copy(&laddr.bt_bdaddr, &unit->hci_bdaddr);
    779        1.3      tron 
    780        1.3      tron 	memset(&raddr, 0, sizeof(raddr));
    781        1.3      tron 	raddr.bt_len = sizeof(raddr);
    782        1.3      tron 	raddr.bt_family = AF_BLUETOOTH;
    783        1.3      tron 	bdaddr_copy(&raddr.bt_bdaddr, bdaddr);
    784        1.3      tron 
    785        1.3      tron 	/*
    786        1.3      tron 	 * There should already be an ACL link up and running before
    787        1.3      tron 	 * the controller sends us SCO connection requests, but you
    788        1.3      tron 	 * never know..
    789        1.3      tron 	 */
    790        1.3      tron 	acl = hci_link_lookup_bdaddr(unit, bdaddr, HCI_LINK_ACL);
    791        1.3      tron 	if (acl == NULL || acl->hl_state != HCI_LINK_OPEN)
    792        1.3      tron 		return NULL;
    793        1.3      tron 
    794        1.3      tron 	LIST_FOREACH(pcb, &sco_pcb, sp_next) {
    795        1.3      tron 		if ((pcb->sp_flags & SP_LISTENING) == 0)
    796        1.3      tron 			continue;
    797        1.3      tron 
    798        1.3      tron 		new = (*pcb->sp_proto->newconn)(pcb->sp_upper, &laddr, &raddr);
    799        1.3      tron 		if (new == NULL)
    800        1.3      tron 			continue;
    801        1.3      tron 
    802        1.3      tron 		/*
    803        1.3      tron 		 * Ok, got new pcb so we can start a new link and fill
    804        1.3      tron 		 * in all the details.
    805        1.3      tron 		 */
    806        1.3      tron 		bdaddr_copy(&new->sp_laddr, &unit->hci_bdaddr);
    807        1.3      tron 		bdaddr_copy(&new->sp_raddr, bdaddr);
    808        1.3      tron 
    809       1.19    plunky 		sco = hci_link_alloc(unit, bdaddr, HCI_LINK_SCO);
    810        1.3      tron 		if (sco == NULL) {
    811       1.24     rmind 			sco_detach_pcb(&new);
    812        1.3      tron 			return NULL;
    813        1.3      tron 		}
    814        1.3      tron 
    815        1.3      tron 		sco->hl_link = hci_acl_open(unit, bdaddr);
    816        1.3      tron 		KASSERT(sco->hl_link == acl);
    817        1.3      tron 
    818        1.3      tron 		sco->hl_sco = new;
    819        1.3      tron 		new->sp_link = sco;
    820        1.3      tron 
    821        1.3      tron 		new->sp_mtu = unit->hci_max_sco_size;
    822        1.3      tron 		return sco;
    823        1.3      tron 	}
    824        1.1   gdamore 
    825        1.1   gdamore 	return NULL;
    826        1.1   gdamore }
    827        1.1   gdamore 
    828        1.1   gdamore /*
    829        1.1   gdamore  * receive SCO packet, we only need to strip the header and send
    830        1.1   gdamore  * it to the right handler
    831        1.1   gdamore  */
    832        1.1   gdamore void
    833        1.1   gdamore hci_sco_recv(struct mbuf *m, struct hci_unit *unit)
    834        1.1   gdamore {
    835        1.1   gdamore 	struct hci_link *link;
    836        1.1   gdamore 	hci_scodata_hdr_t hdr;
    837        1.1   gdamore 	uint16_t handle;
    838        1.1   gdamore 
    839       1.10    plunky 	KASSERT(m != NULL);
    840       1.10    plunky 	KASSERT(unit != NULL);
    841        1.1   gdamore 
    842       1.23    plunky 	if (m->m_pkthdr.len < sizeof(hdr))
    843       1.23    plunky 		goto bad;
    844       1.23    plunky 
    845        1.1   gdamore 	m_copydata(m, 0, sizeof(hdr), &hdr);
    846        1.1   gdamore 	m_adj(m, sizeof(hdr));
    847        1.1   gdamore 
    848       1.23    plunky 	KASSERT(hdr.type == HCI_SCO_DATA_PKT);
    849        1.1   gdamore 
    850       1.23    plunky 	hdr.con_handle = le16toh(hdr.con_handle);
    851       1.23    plunky 	handle = HCI_CON_HANDLE(hdr.con_handle);
    852       1.16    plunky 
    853       1.23    plunky 	if (m->m_pkthdr.len != hdr.length)
    854        1.1   gdamore 		goto bad;
    855        1.1   gdamore 
    856        1.1   gdamore 	link = hci_link_lookup_handle(unit, handle);
    857        1.1   gdamore 	if (link == NULL || link->hl_type == HCI_LINK_ACL) {
    858        1.1   gdamore 		DPRINTF("%s: dumping packet for unknown handle #%d\n",
    859       1.16    plunky 			device_xname(unit->hci_dev), handle);
    860        1.1   gdamore 
    861        1.1   gdamore 		goto bad;
    862        1.1   gdamore 	}
    863        1.1   gdamore 
    864        1.1   gdamore 	(*link->hl_sco->sp_proto->input)(link->hl_sco->sp_upper, m);
    865        1.1   gdamore 	return;
    866        1.1   gdamore 
    867        1.1   gdamore bad:
    868        1.1   gdamore 	m_freem(m);
    869        1.1   gdamore }
    870        1.1   gdamore 
    871        1.1   gdamore void
    872        1.8  christos hci_sco_start(struct hci_link *link)
    873        1.1   gdamore {
    874        1.1   gdamore }
    875        1.1   gdamore 
    876        1.1   gdamore /*
    877        1.1   gdamore  * SCO packets have completed at the controller, so we can
    878        1.1   gdamore  * signal up to free the buffer space.
    879        1.1   gdamore  */
    880        1.1   gdamore void
    881        1.1   gdamore hci_sco_complete(struct hci_link *link, int num)
    882        1.1   gdamore {
    883        1.1   gdamore 
    884        1.1   gdamore 	DPRINTFN(5, "handle #%d (num=%d)\n", link->hl_handle, num);
    885        1.1   gdamore 	link->hl_sco->sp_pending--;
    886        1.1   gdamore 	(*link->hl_sco->sp_proto->complete)(link->hl_sco->sp_upper, num);
    887        1.1   gdamore }
    888        1.1   gdamore 
    889        1.1   gdamore /*******************************************************************************
    890        1.1   gdamore  *
    891        1.1   gdamore  *	Generic HCI Connection alloc/free/lookup etc
    892        1.1   gdamore  */
    893        1.1   gdamore 
    894        1.1   gdamore struct hci_link *
    895       1.19    plunky hci_link_alloc(struct hci_unit *unit, bdaddr_t *bdaddr, uint8_t type)
    896        1.1   gdamore {
    897        1.1   gdamore 	struct hci_link *link;
    898        1.1   gdamore 
    899       1.10    plunky 	KASSERT(unit != NULL);
    900        1.1   gdamore 
    901        1.1   gdamore 	link = malloc(sizeof(struct hci_link), M_BLUETOOTH, M_NOWAIT | M_ZERO);
    902        1.1   gdamore 	if (link == NULL)
    903        1.1   gdamore 		return NULL;
    904        1.1   gdamore 
    905        1.1   gdamore 	link->hl_unit = unit;
    906       1.19    plunky 	link->hl_type = type;
    907        1.1   gdamore 	link->hl_state = HCI_LINK_CLOSED;
    908       1.19    plunky 	bdaddr_copy(&link->hl_bdaddr, bdaddr);
    909        1.1   gdamore 
    910        1.1   gdamore 	/* init ACL portion */
    911       1.12        ad 	callout_init(&link->hl_expire, 0);
    912        1.1   gdamore 	callout_setfunc(&link->hl_expire, hci_acl_timeout, link);
    913        1.1   gdamore 
    914        1.1   gdamore 	TAILQ_INIT(&link->hl_txq);	/* outgoing packets */
    915        1.1   gdamore 	TAILQ_INIT(&link->hl_reqs);	/* request queue */
    916        1.1   gdamore 
    917        1.1   gdamore 	link->hl_mtu = L2CAP_MTU_DEFAULT;		/* L2CAP signal mtu */
    918        1.1   gdamore 	link->hl_flush = L2CAP_FLUSH_TIMO_DEFAULT;	/* flush timeout */
    919        1.1   gdamore 
    920        1.1   gdamore 	/* init SCO portion */
    921        1.1   gdamore 	MBUFQ_INIT(&link->hl_data);
    922        1.1   gdamore 
    923        1.1   gdamore 	/* attach to unit */
    924       1.18    plunky 	TAILQ_INSERT_TAIL(&unit->hci_links, link, hl_next);
    925        1.1   gdamore 	return link;
    926        1.1   gdamore }
    927        1.1   gdamore 
    928        1.1   gdamore void
    929        1.1   gdamore hci_link_free(struct hci_link *link, int err)
    930        1.1   gdamore {
    931        1.1   gdamore 	struct l2cap_req *req;
    932        1.1   gdamore 	struct l2cap_pdu *pdu;
    933        1.4    plunky 	struct l2cap_channel *chan, *next;
    934        1.1   gdamore 
    935       1.10    plunky 	KASSERT(link != NULL);
    936        1.1   gdamore 
    937        1.1   gdamore 	DPRINTF("#%d, type = %d, state = %d, refcnt = %d\n",
    938        1.1   gdamore 		link->hl_handle, link->hl_type,
    939        1.1   gdamore 		link->hl_state, link->hl_refcnt);
    940        1.1   gdamore 
    941        1.1   gdamore 	/* ACL reference count */
    942        1.1   gdamore 	if (link->hl_refcnt > 0) {
    943        1.4    plunky 		next = LIST_FIRST(&l2cap_active_list);
    944        1.4    plunky 		while ((chan = next) != NULL) {
    945        1.4    plunky 			next = LIST_NEXT(chan, lc_ncid);
    946        1.1   gdamore 			if (chan->lc_link == link)
    947        1.1   gdamore 				l2cap_close(chan, err);
    948        1.1   gdamore 		}
    949        1.1   gdamore 	}
    950        1.1   gdamore 	KASSERT(link->hl_refcnt == 0);
    951        1.1   gdamore 
    952        1.1   gdamore 	/* ACL L2CAP requests.. */
    953        1.1   gdamore 	while ((req = TAILQ_FIRST(&link->hl_reqs)) != NULL)
    954        1.1   gdamore 		l2cap_request_free(req);
    955        1.1   gdamore 
    956        1.1   gdamore 	KASSERT(TAILQ_EMPTY(&link->hl_reqs));
    957        1.1   gdamore 
    958        1.1   gdamore 	/* ACL outgoing data queue */
    959        1.1   gdamore 	while ((pdu = TAILQ_FIRST(&link->hl_txq)) != NULL) {
    960        1.1   gdamore 		TAILQ_REMOVE(&link->hl_txq, pdu, lp_next);
    961        1.1   gdamore 		MBUFQ_DRAIN(&pdu->lp_data);
    962        1.1   gdamore 		if (pdu->lp_pending)
    963        1.1   gdamore 			link->hl_unit->hci_num_acl_pkts += pdu->lp_pending;
    964        1.1   gdamore 
    965        1.1   gdamore 		pool_put(&l2cap_pdu_pool, pdu);
    966        1.1   gdamore 	}
    967        1.1   gdamore 
    968        1.1   gdamore 	KASSERT(TAILQ_EMPTY(&link->hl_txq));
    969        1.1   gdamore 
    970        1.1   gdamore 	/* ACL incoming data packet */
    971        1.1   gdamore 	if (link->hl_rxp != NULL) {
    972        1.1   gdamore 		m_freem(link->hl_rxp);
    973        1.1   gdamore 		link->hl_rxp = NULL;
    974        1.1   gdamore 	}
    975        1.1   gdamore 
    976        1.1   gdamore 	/* SCO master ACL link */
    977        1.1   gdamore 	if (link->hl_link != NULL) {
    978        1.1   gdamore 		hci_acl_close(link->hl_link, err);
    979        1.1   gdamore 		link->hl_link = NULL;
    980        1.1   gdamore 	}
    981        1.1   gdamore 
    982        1.1   gdamore 	/* SCO pcb */
    983        1.1   gdamore 	if (link->hl_sco != NULL) {
    984        1.1   gdamore 		struct sco_pcb *pcb;
    985        1.1   gdamore 
    986        1.1   gdamore 		pcb = link->hl_sco;
    987        1.1   gdamore 		pcb->sp_link = NULL;
    988        1.1   gdamore 		link->hl_sco = NULL;
    989        1.1   gdamore 		(*pcb->sp_proto->disconnected)(pcb->sp_upper, err);
    990        1.1   gdamore 	}
    991        1.1   gdamore 
    992        1.1   gdamore 	/* flush any SCO data */
    993        1.1   gdamore 	MBUFQ_DRAIN(&link->hl_data);
    994        1.1   gdamore 
    995        1.1   gdamore 	/*
    996        1.1   gdamore 	 * Halt the callout - if its already running we cannot free the
    997        1.1   gdamore 	 * link structure but the timeout function will call us back in
    998        1.1   gdamore 	 * any case.
    999        1.1   gdamore 	 */
   1000        1.1   gdamore 	link->hl_state = HCI_LINK_CLOSED;
   1001        1.1   gdamore 	callout_stop(&link->hl_expire);
   1002        1.1   gdamore 	if (callout_invoking(&link->hl_expire))
   1003        1.1   gdamore 		return;
   1004        1.1   gdamore 
   1005       1.15    plunky 	callout_destroy(&link->hl_expire);
   1006       1.15    plunky 
   1007       1.14    plunky 	/*
   1008       1.14    plunky 	 * If we made a note of clock offset, keep it in a memo
   1009       1.14    plunky 	 * to facilitate reconnections to this device
   1010       1.14    plunky 	 */
   1011       1.14    plunky 	if (link->hl_clock != 0) {
   1012       1.14    plunky 		struct hci_memo *memo;
   1013       1.14    plunky 
   1014       1.14    plunky 		memo = hci_memo_new(link->hl_unit, &link->hl_bdaddr);
   1015       1.14    plunky 		if (memo != NULL)
   1016       1.14    plunky 			memo->clock_offset = link->hl_clock;
   1017       1.14    plunky 	}
   1018       1.14    plunky 
   1019        1.1   gdamore 	TAILQ_REMOVE(&link->hl_unit->hci_links, link, hl_next);
   1020        1.1   gdamore 	free(link, M_BLUETOOTH);
   1021        1.1   gdamore }
   1022        1.1   gdamore 
   1023        1.1   gdamore /*
   1024        1.1   gdamore  * Lookup HCI link by address and type. Note that for SCO links there may
   1025        1.1   gdamore  * be more than one link per address, so we only return links with no
   1026        1.1   gdamore  * handle (ie new links)
   1027        1.1   gdamore  */
   1028        1.1   gdamore struct hci_link *
   1029       1.19    plunky hci_link_lookup_bdaddr(struct hci_unit *unit, bdaddr_t *bdaddr, uint8_t type)
   1030        1.1   gdamore {
   1031        1.1   gdamore 	struct hci_link *link;
   1032        1.1   gdamore 
   1033       1.10    plunky 	KASSERT(unit != NULL);
   1034       1.10    plunky 	KASSERT(bdaddr != NULL);
   1035        1.1   gdamore 
   1036        1.1   gdamore 	TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
   1037        1.1   gdamore 		if (link->hl_type != type)
   1038        1.1   gdamore 			continue;
   1039        1.1   gdamore 
   1040        1.1   gdamore 		if (type == HCI_LINK_SCO && link->hl_handle != 0)
   1041        1.1   gdamore 			continue;
   1042        1.1   gdamore 
   1043        1.1   gdamore 		if (bdaddr_same(&link->hl_bdaddr, bdaddr))
   1044        1.1   gdamore 			break;
   1045        1.1   gdamore 	}
   1046        1.1   gdamore 
   1047        1.1   gdamore 	return link;
   1048        1.1   gdamore }
   1049        1.1   gdamore 
   1050        1.1   gdamore struct hci_link *
   1051        1.1   gdamore hci_link_lookup_handle(struct hci_unit *unit, uint16_t handle)
   1052        1.1   gdamore {
   1053        1.1   gdamore 	struct hci_link *link;
   1054        1.1   gdamore 
   1055       1.10    plunky 	KASSERT(unit != NULL);
   1056        1.1   gdamore 
   1057        1.1   gdamore 	TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
   1058        1.1   gdamore 		if (handle == link->hl_handle)
   1059        1.1   gdamore 			break;
   1060        1.1   gdamore 	}
   1061        1.1   gdamore 
   1062        1.1   gdamore 	return link;
   1063        1.1   gdamore }
   1064