Home | History | Annotate | Line # | Download | only in netbt
hci_link.c revision 1.16.10.1
      1  1.16.10.1   keiichi /*	$NetBSD: hci_link.c,v 1.16.10.1 2008/03/24 07:16:24 keiichi 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.16.10.1   keiichi __KERNEL_RCSID(0, "$NetBSD: hci_link.c,v 1.16.10.1 2008/03/24 07:16:24 keiichi 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.16.10.1   keiichi 		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.16.10.1   keiichi 		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.3      tron  * For now, we accept all connections but it would be better to check
    166        1.3      tron  * the L2CAP listen list and only accept when there is a listener
    167        1.3      tron  * available.
    168        1.3      tron  *
    169        1.3      tron  * There should not be a link to the same bdaddr already, we check
    170        1.3      tron  * anyway though its left unhandled for now.
    171        1.1   gdamore  */
    172        1.1   gdamore struct hci_link *
    173        1.1   gdamore hci_acl_newconn(struct hci_unit *unit, bdaddr_t *bdaddr)
    174        1.1   gdamore {
    175        1.1   gdamore 	struct hci_link *link;
    176        1.1   gdamore 
    177        1.3      tron 	link = hci_link_lookup_bdaddr(unit, bdaddr, HCI_LINK_ACL);
    178        1.3      tron 	if (link != NULL)
    179        1.3      tron 		return NULL;
    180        1.3      tron 
    181  1.16.10.1   keiichi 	link = hci_link_alloc(unit, bdaddr, HCI_LINK_ACL);
    182        1.1   gdamore 	if (link != NULL) {
    183        1.1   gdamore 		link->hl_state = HCI_LINK_WAIT_CONNECT;
    184        1.1   gdamore 
    185        1.1   gdamore 		if (hci_acl_expiry > 0)
    186        1.1   gdamore 			callout_schedule(&link->hl_expire, hci_acl_expiry * hz);
    187        1.1   gdamore 	}
    188        1.1   gdamore 
    189        1.1   gdamore 	return link;
    190        1.1   gdamore }
    191        1.1   gdamore 
    192        1.1   gdamore void
    193        1.1   gdamore hci_acl_timeout(void *arg)
    194        1.1   gdamore {
    195        1.1   gdamore 	struct hci_link *link = arg;
    196        1.1   gdamore 	hci_discon_cp cp;
    197        1.1   gdamore 	int s, err;
    198        1.1   gdamore 
    199        1.1   gdamore 	s = splsoftnet();
    200        1.1   gdamore 	callout_ack(&link->hl_expire);
    201        1.1   gdamore 
    202        1.1   gdamore 	if (link->hl_refcnt > 0)
    203        1.1   gdamore 		goto out;
    204        1.1   gdamore 
    205        1.1   gdamore 	DPRINTF("link #%d expired\n", link->hl_handle);
    206        1.1   gdamore 
    207        1.1   gdamore 	switch (link->hl_state) {
    208        1.1   gdamore 	case HCI_LINK_CLOSED:
    209        1.1   gdamore 	case HCI_LINK_WAIT_CONNECT:
    210        1.1   gdamore 		hci_link_free(link, ECONNRESET);
    211        1.1   gdamore 		break;
    212        1.1   gdamore 
    213       1.11    plunky 	case HCI_LINK_WAIT_AUTH:
    214       1.11    plunky 	case HCI_LINK_WAIT_ENCRYPT:
    215       1.11    plunky 	case HCI_LINK_WAIT_SECURE:
    216        1.1   gdamore 	case HCI_LINK_OPEN:
    217        1.1   gdamore 		cp.con_handle = htole16(link->hl_handle);
    218        1.1   gdamore 		cp.reason = 0x13; /* "Remote User Terminated Connection" */
    219        1.1   gdamore 
    220        1.1   gdamore 		err = hci_send_cmd(link->hl_unit, HCI_CMD_DISCONNECT,
    221        1.1   gdamore 					&cp, sizeof(cp));
    222        1.1   gdamore 
    223        1.6  christos 		if (err) {
    224        1.1   gdamore 			DPRINTF("error %d sending HCI_CMD_DISCONNECT\n",
    225        1.6  christos 			    err);
    226        1.6  christos 		}
    227        1.1   gdamore 
    228        1.1   gdamore 		break;
    229        1.1   gdamore 
    230        1.1   gdamore 	default:
    231        1.1   gdamore 		UNKNOWN(link->hl_state);
    232        1.1   gdamore 		break;
    233        1.1   gdamore 	}
    234        1.1   gdamore 
    235        1.1   gdamore out:
    236        1.1   gdamore 	splx(s);
    237        1.1   gdamore }
    238        1.1   gdamore 
    239        1.1   gdamore /*
    240       1.11    plunky  * Initiate any Link Mode change requests.
    241       1.11    plunky  */
    242       1.11    plunky int
    243       1.11    plunky hci_acl_setmode(struct hci_link *link)
    244       1.11    plunky {
    245       1.11    plunky 	int err;
    246       1.11    plunky 
    247       1.11    plunky 	KASSERT(link != NULL);
    248       1.11    plunky 	KASSERT(link->hl_unit != NULL);
    249       1.11    plunky 
    250       1.11    plunky 	if (link->hl_state != HCI_LINK_OPEN)
    251       1.11    plunky 		return EINPROGRESS;
    252       1.11    plunky 
    253       1.11    plunky 	if ((link->hl_flags & HCI_LINK_AUTH_REQ)
    254       1.11    plunky 	    && !(link->hl_flags & HCI_LINK_AUTH)) {
    255       1.11    plunky 		hci_auth_req_cp cp;
    256       1.11    plunky 
    257       1.11    plunky 		DPRINTF("requesting auth for handle #%d\n",
    258       1.11    plunky 			link->hl_handle);
    259       1.11    plunky 
    260       1.11    plunky 		link->hl_state = HCI_LINK_WAIT_AUTH;
    261       1.11    plunky 		cp.con_handle = htole16(link->hl_handle);
    262       1.11    plunky 		err = hci_send_cmd(link->hl_unit, HCI_CMD_AUTH_REQ,
    263       1.11    plunky 				   &cp, sizeof(cp));
    264       1.11    plunky 
    265       1.11    plunky 		return (err == 0 ? EINPROGRESS : err);
    266       1.11    plunky 	}
    267       1.11    plunky 
    268       1.11    plunky 	if ((link->hl_flags & HCI_LINK_ENCRYPT_REQ)
    269       1.11    plunky 	    && !(link->hl_flags & HCI_LINK_ENCRYPT)) {
    270       1.11    plunky 		hci_set_con_encryption_cp cp;
    271       1.11    plunky 
    272       1.11    plunky 		/* XXX we should check features for encryption capability */
    273       1.11    plunky 
    274       1.11    plunky 		DPRINTF("requesting encryption 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_ENCRYPT;
    278       1.11    plunky 		cp.con_handle = htole16(link->hl_handle);
    279       1.11    plunky 		cp.encryption_enable = 0x01;
    280       1.11    plunky 
    281       1.11    plunky 		err = hci_send_cmd(link->hl_unit, HCI_CMD_SET_CON_ENCRYPTION,
    282       1.11    plunky 				   &cp, sizeof(cp));
    283       1.11    plunky 
    284       1.11    plunky 		return (err == 0 ? EINPROGRESS : err);
    285       1.11    plunky 	}
    286       1.11    plunky 
    287       1.11    plunky 	if ((link->hl_flags & HCI_LINK_SECURE_REQ)) {
    288       1.11    plunky 		hci_change_con_link_key_cp cp;
    289       1.11    plunky 
    290       1.11    plunky 		/* always change link key for SECURE requests */
    291       1.11    plunky 		link->hl_flags &= ~HCI_LINK_SECURE;
    292       1.11    plunky 
    293       1.11    plunky 		DPRINTF("changing link key for handle #%d\n",
    294       1.11    plunky 			link->hl_handle);
    295       1.11    plunky 
    296       1.11    plunky 		link->hl_state = HCI_LINK_WAIT_SECURE;
    297       1.11    plunky 		cp.con_handle = htole16(link->hl_handle);
    298       1.11    plunky 
    299       1.11    plunky 		err = hci_send_cmd(link->hl_unit, HCI_CMD_CHANGE_CON_LINK_KEY,
    300       1.11    plunky 				   &cp, sizeof(cp));
    301       1.11    plunky 
    302       1.11    plunky 		return (err == 0 ? EINPROGRESS : err);
    303       1.11    plunky 	}
    304       1.11    plunky 
    305       1.11    plunky 	return 0;
    306       1.11    plunky }
    307       1.11    plunky 
    308       1.11    plunky /*
    309       1.11    plunky  * Link Mode changed.
    310       1.11    plunky  *
    311       1.11    plunky  * This is called from event handlers when the mode change
    312       1.11    plunky  * is complete. We notify upstream and restart the link.
    313       1.11    plunky  */
    314       1.11    plunky void
    315       1.11    plunky hci_acl_linkmode(struct hci_link *link)
    316       1.11    plunky {
    317       1.11    plunky 	struct l2cap_channel *chan, *next;
    318       1.11    plunky 	int err, mode = 0;
    319       1.11    plunky 
    320       1.11    plunky 	DPRINTF("handle #%d, auth %s, encrypt %s, secure %s\n",
    321       1.11    plunky 		link->hl_handle,
    322       1.11    plunky 		(link->hl_flags & HCI_LINK_AUTH ? "on" : "off"),
    323       1.11    plunky 		(link->hl_flags & HCI_LINK_ENCRYPT ? "on" : "off"),
    324       1.11    plunky 		(link->hl_flags & HCI_LINK_SECURE ? "on" : "off"));
    325       1.11    plunky 
    326       1.11    plunky 	if (link->hl_flags & HCI_LINK_AUTH)
    327       1.11    plunky 		mode |= L2CAP_LM_AUTH;
    328       1.11    plunky 
    329       1.11    plunky 	if (link->hl_flags & HCI_LINK_ENCRYPT)
    330       1.11    plunky 		mode |= L2CAP_LM_ENCRYPT;
    331       1.11    plunky 
    332       1.11    plunky 	if (link->hl_flags & HCI_LINK_SECURE)
    333       1.11    plunky 		mode |= L2CAP_LM_SECURE;
    334       1.11    plunky 
    335       1.11    plunky 	/*
    336       1.11    plunky 	 * The link state will only be OPEN here if the mode change
    337       1.11    plunky 	 * was successful. So, we can proceed with L2CAP connections,
    338       1.11    plunky 	 * or notify already establshed channels, to allow any that
    339       1.11    plunky 	 * are dissatisfied to disconnect before we restart.
    340       1.11    plunky 	 */
    341       1.11    plunky 	next = LIST_FIRST(&l2cap_active_list);
    342       1.11    plunky 	while ((chan = next) != NULL) {
    343       1.11    plunky 		next = LIST_NEXT(chan, lc_ncid);
    344       1.11    plunky 
    345       1.11    plunky 		if (chan->lc_link != link)
    346       1.11    plunky 			continue;
    347       1.11    plunky 
    348       1.11    plunky 		switch(chan->lc_state) {
    349       1.11    plunky 		case L2CAP_WAIT_SEND_CONNECT_REQ: /* we are connecting */
    350       1.11    plunky 			if ((mode & chan->lc_mode) != chan->lc_mode) {
    351       1.11    plunky 				l2cap_close(chan, ECONNABORTED);
    352       1.11    plunky 				break;
    353       1.11    plunky 			}
    354       1.11    plunky 
    355       1.11    plunky 			chan->lc_state = L2CAP_WAIT_RECV_CONNECT_RSP;
    356       1.11    plunky 			err = l2cap_send_connect_req(chan);
    357       1.11    plunky 			if (err) {
    358       1.11    plunky 				l2cap_close(chan, err);
    359       1.11    plunky 				break;
    360       1.11    plunky 			}
    361       1.11    plunky 			break;
    362       1.11    plunky 
    363       1.11    plunky 		case L2CAP_WAIT_SEND_CONNECT_RSP: /* they are connecting */
    364       1.11    plunky 			if ((mode & chan->lc_mode) != chan->lc_mode) {
    365       1.11    plunky 				l2cap_send_connect_rsp(link, chan->lc_ident,
    366       1.11    plunky 							0, chan->lc_rcid,
    367       1.11    plunky 							L2CAP_SECURITY_BLOCK);
    368       1.11    plunky 
    369       1.11    plunky 				l2cap_close(chan, ECONNABORTED);
    370       1.11    plunky 				break;
    371       1.11    plunky 			}
    372       1.11    plunky 
    373       1.11    plunky 			l2cap_send_connect_rsp(link, chan->lc_ident,
    374       1.11    plunky 						chan->lc_lcid, chan->lc_rcid,
    375       1.11    plunky 						L2CAP_SUCCESS);
    376       1.11    plunky 
    377       1.11    plunky 			chan->lc_state = L2CAP_WAIT_CONFIG;
    378       1.11    plunky 			chan->lc_flags |= (L2CAP_WAIT_CONFIG_RSP | L2CAP_WAIT_CONFIG_REQ);
    379       1.11    plunky 			err = l2cap_send_config_req(chan);
    380       1.11    plunky 			if (err) {
    381       1.11    plunky 				l2cap_close(chan, err);
    382       1.11    plunky 				break;
    383       1.11    plunky 			}
    384       1.11    plunky 			break;
    385       1.11    plunky 
    386       1.11    plunky 		case L2CAP_WAIT_RECV_CONNECT_RSP:
    387       1.11    plunky 		case L2CAP_WAIT_CONFIG:
    388       1.11    plunky 		case L2CAP_OPEN: /* already established */
    389       1.11    plunky 			(*chan->lc_proto->linkmode)(chan->lc_upper, mode);
    390       1.11    plunky 			break;
    391       1.11    plunky 
    392       1.11    plunky 		default:
    393       1.11    plunky 			break;
    394       1.11    plunky 		}
    395       1.11    plunky 	}
    396       1.11    plunky 
    397       1.11    plunky 	link->hl_state = HCI_LINK_OPEN;
    398       1.11    plunky 	hci_acl_start(link);
    399       1.11    plunky }
    400       1.11    plunky 
    401       1.11    plunky /*
    402        1.1   gdamore  * Receive ACL Data
    403        1.1   gdamore  *
    404        1.1   gdamore  * we accumulate packet fragments on the hci_link structure
    405        1.1   gdamore  * until a full L2CAP frame is ready, then send it on.
    406        1.1   gdamore  */
    407        1.1   gdamore void
    408        1.1   gdamore hci_acl_recv(struct mbuf *m, struct hci_unit *unit)
    409        1.1   gdamore {
    410        1.1   gdamore 	struct hci_link *link;
    411        1.1   gdamore 	hci_acldata_hdr_t hdr;
    412        1.1   gdamore 	uint16_t handle, want;
    413        1.1   gdamore 	int pb, got;
    414        1.1   gdamore 
    415       1.10    plunky 	KASSERT(m != NULL);
    416       1.10    plunky 	KASSERT(unit != NULL);
    417        1.1   gdamore 
    418        1.1   gdamore 	KASSERT(m->m_pkthdr.len >= sizeof(hdr));
    419        1.1   gdamore 	m_copydata(m, 0, sizeof(hdr), &hdr);
    420        1.1   gdamore 	m_adj(m, sizeof(hdr));
    421        1.1   gdamore 
    422        1.1   gdamore #ifdef DIAGNOSTIC
    423        1.1   gdamore 	if (hdr.type != HCI_ACL_DATA_PKT) {
    424       1.16    plunky 		aprint_error_dev(unit->hci_dev, "bad ACL packet type\n");
    425        1.1   gdamore 		goto bad;
    426        1.1   gdamore 	}
    427        1.1   gdamore 
    428        1.1   gdamore 	if (m->m_pkthdr.len != le16toh(hdr.length)) {
    429       1.16    plunky 		aprint_error_dev(unit->hci_dev,
    430       1.16    plunky 		    "bad ACL packet length (%d != %d)\n",
    431       1.16    plunky 		    m->m_pkthdr.len, le16toh(hdr.length));
    432        1.1   gdamore 		goto bad;
    433        1.1   gdamore 	}
    434        1.1   gdamore #endif
    435        1.1   gdamore 
    436        1.1   gdamore 	hdr.length = le16toh(hdr.length);
    437        1.1   gdamore 	hdr.con_handle = le16toh(hdr.con_handle);
    438        1.1   gdamore 	handle = HCI_CON_HANDLE(hdr.con_handle);
    439        1.1   gdamore 	pb = HCI_PB_FLAG(hdr.con_handle);
    440        1.1   gdamore 
    441        1.1   gdamore 	link = hci_link_lookup_handle(unit, handle);
    442        1.1   gdamore 	if (link == NULL) {
    443        1.1   gdamore 		hci_discon_cp cp;
    444        1.1   gdamore 
    445        1.1   gdamore 		DPRINTF("%s: dumping packet for unknown handle #%d\n",
    446       1.16    plunky 			device_xname(unit->hci_dev), handle);
    447        1.1   gdamore 
    448        1.1   gdamore 		/*
    449        1.1   gdamore 		 * There is no way to find out what this connection handle is
    450        1.1   gdamore 		 * for, just get rid of it. This may happen, if a USB dongle
    451        1.1   gdamore 		 * is plugged into a self powered hub and does not reset when
    452        1.1   gdamore 		 * the system is shut down.
    453        1.1   gdamore 		 */
    454        1.1   gdamore 		cp.con_handle = htole16(handle);
    455        1.1   gdamore 		cp.reason = 0x13; /* "Remote User Terminated Connection" */
    456        1.1   gdamore 		hci_send_cmd(unit, HCI_CMD_DISCONNECT, &cp, sizeof(cp));
    457        1.1   gdamore 		goto bad;
    458        1.1   gdamore 	}
    459        1.1   gdamore 
    460        1.1   gdamore 	switch (pb) {
    461        1.1   gdamore 	case HCI_PACKET_START:
    462        1.1   gdamore 		if (link->hl_rxp != NULL)
    463       1.16    plunky 			aprint_error_dev(unit->hci_dev,
    464       1.16    plunky 			    "dropped incomplete ACL packet\n");
    465        1.1   gdamore 
    466        1.1   gdamore 		if (m->m_pkthdr.len < sizeof(l2cap_hdr_t)) {
    467       1.16    plunky 			aprint_error_dev(unit->hci_dev, "short ACL packet\n");
    468        1.1   gdamore 			goto bad;
    469        1.1   gdamore 		}
    470        1.1   gdamore 
    471        1.1   gdamore 		link->hl_rxp = m;
    472        1.1   gdamore 		got = m->m_pkthdr.len;
    473        1.1   gdamore 		break;
    474        1.1   gdamore 
    475        1.1   gdamore 	case HCI_PACKET_FRAGMENT:
    476        1.1   gdamore 		if (link->hl_rxp == NULL) {
    477       1.16    plunky 			aprint_error_dev(unit->hci_dev,
    478       1.16    plunky 			    "unexpected packet fragment\n");
    479        1.1   gdamore 
    480        1.1   gdamore 			goto bad;
    481        1.1   gdamore 		}
    482        1.1   gdamore 
    483        1.1   gdamore 		got = m->m_pkthdr.len + link->hl_rxp->m_pkthdr.len;
    484        1.1   gdamore 		m_cat(link->hl_rxp, m);
    485        1.1   gdamore 		m = link->hl_rxp;
    486        1.1   gdamore 		m->m_pkthdr.len = got;
    487        1.1   gdamore 		break;
    488        1.1   gdamore 
    489        1.1   gdamore 	default:
    490       1.16    plunky 		aprint_error_dev(unit->hci_dev, "unknown packet type\n");
    491        1.1   gdamore 		goto bad;
    492        1.1   gdamore 	}
    493        1.1   gdamore 
    494        1.1   gdamore 	m_copydata(m, 0, sizeof(want), &want);
    495        1.1   gdamore 	want = le16toh(want) + sizeof(l2cap_hdr_t) - got;
    496        1.1   gdamore 
    497        1.1   gdamore 	if (want > 0)
    498        1.1   gdamore 		return;
    499        1.1   gdamore 
    500        1.1   gdamore 	link->hl_rxp = NULL;
    501        1.1   gdamore 
    502        1.1   gdamore 	if (want == 0) {
    503        1.1   gdamore 		l2cap_recv_frame(m, link);
    504        1.1   gdamore 		return;
    505        1.1   gdamore 	}
    506        1.1   gdamore 
    507        1.1   gdamore bad:
    508        1.1   gdamore 	m_freem(m);
    509        1.1   gdamore }
    510        1.1   gdamore 
    511        1.1   gdamore /*
    512        1.1   gdamore  * Send ACL data on link
    513        1.1   gdamore  *
    514        1.1   gdamore  * We must fragment packets into chunks of less than unit->hci_max_acl_size and
    515        1.1   gdamore  * prepend a relevant ACL header to each fragment. We keep a PDU structure
    516        1.1   gdamore  * attached to the link, so that completed fragments can be marked off and
    517        1.1   gdamore  * more data requested from above once the PDU is sent.
    518        1.1   gdamore  */
    519        1.1   gdamore int
    520        1.1   gdamore hci_acl_send(struct mbuf *m, struct hci_link *link,
    521        1.1   gdamore 		struct l2cap_channel *chan)
    522        1.1   gdamore {
    523        1.1   gdamore 	struct l2cap_pdu *pdu;
    524        1.1   gdamore 	struct mbuf *n = NULL;
    525        1.1   gdamore 	int plen, mlen, num = 0;
    526        1.1   gdamore 
    527       1.10    plunky 	KASSERT(link != NULL);
    528       1.10    plunky 	KASSERT(m != NULL);
    529        1.1   gdamore 	KASSERT(m->m_flags & M_PKTHDR);
    530        1.1   gdamore 	KASSERT(m->m_pkthdr.len > 0);
    531        1.1   gdamore 
    532        1.1   gdamore 	if (link->hl_state == HCI_LINK_CLOSED) {
    533        1.1   gdamore 		m_freem(m);
    534        1.1   gdamore 		return ENETDOWN;
    535        1.1   gdamore 	}
    536        1.1   gdamore 
    537        1.1   gdamore 	pdu = pool_get(&l2cap_pdu_pool, PR_NOWAIT);
    538        1.1   gdamore 	if (pdu == NULL)
    539        1.1   gdamore 		goto nomem;
    540        1.1   gdamore 
    541        1.1   gdamore 	pdu->lp_chan = chan;
    542        1.1   gdamore 	pdu->lp_pending = 0;
    543        1.1   gdamore 	MBUFQ_INIT(&pdu->lp_data);
    544        1.1   gdamore 
    545        1.1   gdamore 	plen = m->m_pkthdr.len;
    546        1.1   gdamore 	mlen = link->hl_unit->hci_max_acl_size;
    547        1.1   gdamore 
    548        1.1   gdamore 	DPRINTFN(5, "%s: handle #%d, plen = %d, max = %d\n",
    549       1.16    plunky 		device_xname(link->hl_unit->hci_dev), link->hl_handle, plen, mlen);
    550        1.1   gdamore 
    551        1.1   gdamore 	while (plen > 0) {
    552        1.1   gdamore 		if (plen > mlen) {
    553        1.1   gdamore 			n = m_split(m, mlen, M_DONTWAIT);
    554        1.1   gdamore 			if (n == NULL)
    555        1.1   gdamore 				goto nomem;
    556        1.1   gdamore 		} else {
    557        1.1   gdamore 			mlen = plen;
    558        1.1   gdamore 		}
    559        1.1   gdamore 
    560        1.1   gdamore 		if (num++ == 0)
    561        1.1   gdamore 			m->m_flags |= M_PROTO1;	/* tag first fragment */
    562        1.1   gdamore 
    563        1.1   gdamore 		DPRINTFN(10, "chunk of %d (plen = %d) bytes\n", mlen, plen);
    564        1.1   gdamore 		MBUFQ_ENQUEUE(&pdu->lp_data, m);
    565        1.1   gdamore 		m = n;
    566        1.1   gdamore 		plen -= mlen;
    567        1.1   gdamore 	}
    568        1.1   gdamore 
    569        1.1   gdamore 	TAILQ_INSERT_TAIL(&link->hl_txq, pdu, lp_next);
    570        1.1   gdamore 	link->hl_txqlen += num;
    571        1.1   gdamore 
    572        1.1   gdamore 	hci_acl_start(link);
    573        1.1   gdamore 
    574        1.1   gdamore 	return 0;
    575        1.1   gdamore 
    576        1.1   gdamore nomem:
    577        1.1   gdamore 	if (m) m_freem(m);
    578        1.1   gdamore 	if (pdu) {
    579        1.1   gdamore 		MBUFQ_DRAIN(&pdu->lp_data);
    580        1.1   gdamore 		pool_put(&l2cap_pdu_pool, pdu);
    581        1.1   gdamore 	}
    582        1.1   gdamore 
    583        1.1   gdamore 	return ENOMEM;
    584        1.1   gdamore }
    585        1.1   gdamore 
    586        1.1   gdamore /*
    587        1.1   gdamore  * Start sending ACL data on link.
    588        1.1   gdamore  *
    589       1.11    plunky  *	This is called when the queue may need restarting: as new data
    590       1.11    plunky  * is queued, after link mode changes have completed, or when device
    591       1.11    plunky  * buffers have cleared.
    592       1.11    plunky  *
    593        1.1   gdamore  *	We may use all the available packet slots. The reason that we add
    594        1.1   gdamore  * the ACL encapsulation here rather than in hci_acl_send() is that L2CAP
    595        1.1   gdamore  * signal packets may be queued before the handle is given to us..
    596        1.1   gdamore  */
    597        1.1   gdamore void
    598        1.1   gdamore hci_acl_start(struct hci_link *link)
    599        1.1   gdamore {
    600        1.1   gdamore 	struct hci_unit *unit;
    601        1.1   gdamore 	hci_acldata_hdr_t *hdr;
    602        1.1   gdamore 	struct l2cap_pdu *pdu;
    603        1.1   gdamore 	struct mbuf *m;
    604        1.1   gdamore 	uint16_t handle;
    605        1.1   gdamore 
    606       1.10    plunky 	KASSERT(link != NULL);
    607        1.1   gdamore 
    608        1.1   gdamore 	unit = link->hl_unit;
    609       1.10    plunky 	KASSERT(unit != NULL);
    610        1.1   gdamore 
    611        1.1   gdamore 	/* this is mainly to block ourselves (below) */
    612        1.1   gdamore 	if (link->hl_state != HCI_LINK_OPEN)
    613        1.1   gdamore 		return;
    614        1.1   gdamore 
    615        1.1   gdamore 	if (link->hl_txqlen == 0 || unit->hci_num_acl_pkts == 0)
    616        1.1   gdamore 		return;
    617        1.1   gdamore 
    618        1.1   gdamore 	/* find first PDU with data to send */
    619        1.1   gdamore 	pdu = TAILQ_FIRST(&link->hl_txq);
    620        1.1   gdamore 	for (;;) {
    621        1.1   gdamore 		if (pdu == NULL)
    622        1.1   gdamore 			return;
    623        1.1   gdamore 
    624        1.1   gdamore 		if (MBUFQ_FIRST(&pdu->lp_data) != NULL)
    625        1.1   gdamore 			break;
    626        1.1   gdamore 
    627        1.1   gdamore 		pdu = TAILQ_NEXT(pdu, lp_next);
    628        1.1   gdamore 	}
    629        1.1   gdamore 
    630        1.1   gdamore 	while (unit->hci_num_acl_pkts > 0) {
    631        1.1   gdamore 		MBUFQ_DEQUEUE(&pdu->lp_data, m);
    632        1.1   gdamore 		KASSERT(m != NULL);
    633        1.1   gdamore 
    634        1.1   gdamore 		if (m->m_flags & M_PROTO1)
    635        1.1   gdamore 			handle = HCI_MK_CON_HANDLE(link->hl_handle,
    636        1.1   gdamore 						HCI_PACKET_START, 0);
    637        1.1   gdamore 		else
    638        1.1   gdamore 			handle = HCI_MK_CON_HANDLE(link->hl_handle,
    639        1.1   gdamore 						HCI_PACKET_FRAGMENT, 0);
    640        1.1   gdamore 
    641        1.1   gdamore 		M_PREPEND(m, sizeof(*hdr), M_DONTWAIT);
    642        1.1   gdamore 		if (m == NULL)
    643        1.1   gdamore 			break;
    644        1.1   gdamore 
    645        1.1   gdamore 		hdr = mtod(m, hci_acldata_hdr_t *);
    646        1.1   gdamore 		hdr->type = HCI_ACL_DATA_PKT;
    647        1.1   gdamore 		hdr->con_handle = htole16(handle);
    648        1.1   gdamore 		hdr->length = htole16(m->m_pkthdr.len - sizeof(*hdr));
    649        1.1   gdamore 
    650        1.1   gdamore 		link->hl_txqlen--;
    651        1.1   gdamore 		pdu->lp_pending++;
    652        1.1   gdamore 
    653        1.1   gdamore 		hci_output_acl(unit, m);
    654        1.1   gdamore 
    655        1.1   gdamore 		if (MBUFQ_FIRST(&pdu->lp_data) == NULL) {
    656        1.1   gdamore 			if (pdu->lp_chan) {
    657        1.1   gdamore 				/*
    658        1.1   gdamore 				 * This should enable streaming of PDUs - when
    659        1.1   gdamore 				 * we have placed all the fragments on the acl
    660        1.1   gdamore 				 * output queue, we trigger the L2CAP layer to
    661        1.1   gdamore 				 * send us down one more. Use a false state so
    662        1.1   gdamore 				 * we dont run into ourselves coming back from
    663        1.1   gdamore 				 * the future..
    664        1.1   gdamore 				 */
    665        1.1   gdamore 				link->hl_state = HCI_LINK_BLOCK;
    666        1.1   gdamore 				l2cap_start(pdu->lp_chan);
    667        1.1   gdamore 				link->hl_state = HCI_LINK_OPEN;
    668        1.1   gdamore 			}
    669        1.1   gdamore 
    670        1.1   gdamore 			pdu = TAILQ_NEXT(pdu, lp_next);
    671        1.1   gdamore 			if (pdu == NULL)
    672        1.1   gdamore 				break;
    673        1.1   gdamore 		}
    674        1.1   gdamore 	}
    675        1.1   gdamore 
    676        1.1   gdamore 	/*
    677        1.1   gdamore 	 * We had our turn now, move to the back of the queue to let
    678        1.1   gdamore 	 * other links have a go at the output buffers..
    679        1.1   gdamore 	 */
    680        1.1   gdamore 	if (TAILQ_NEXT(link, hl_next)) {
    681        1.1   gdamore 		TAILQ_REMOVE(&unit->hci_links, link, hl_next);
    682        1.1   gdamore 		TAILQ_INSERT_TAIL(&unit->hci_links, link, hl_next);
    683        1.1   gdamore 	}
    684        1.1   gdamore }
    685        1.1   gdamore 
    686        1.1   gdamore /*
    687        1.1   gdamore  * Confirm ACL packets cleared from Controller buffers. We scan our PDU
    688        1.1   gdamore  * list to clear pending fragments and signal upstream for more data
    689        1.1   gdamore  * when a PDU is complete.
    690        1.1   gdamore  */
    691        1.1   gdamore void
    692        1.1   gdamore hci_acl_complete(struct hci_link *link, int num)
    693        1.1   gdamore {
    694        1.1   gdamore 	struct l2cap_pdu *pdu;
    695        1.1   gdamore 	struct l2cap_channel *chan;
    696        1.1   gdamore 
    697        1.1   gdamore 	DPRINTFN(5, "handle #%d (%d)\n", link->hl_handle, num);
    698        1.1   gdamore 
    699        1.1   gdamore 	while (num > 0) {
    700        1.1   gdamore 		pdu = TAILQ_FIRST(&link->hl_txq);
    701        1.1   gdamore 		if (pdu == NULL) {
    702       1.16    plunky 			aprint_error_dev(link->hl_unit->hci_dev,
    703       1.16    plunky 			    "%d packets completed on handle #%x but none pending!\n",
    704       1.16    plunky 			    num, link->hl_handle);
    705       1.16    plunky 
    706        1.1   gdamore 			return;
    707        1.1   gdamore 		}
    708        1.1   gdamore 
    709        1.1   gdamore 		if (num >= pdu->lp_pending) {
    710        1.1   gdamore 			num -= pdu->lp_pending;
    711        1.1   gdamore 			pdu->lp_pending = 0;
    712        1.1   gdamore 
    713        1.1   gdamore 			if (MBUFQ_FIRST(&pdu->lp_data) == NULL) {
    714        1.1   gdamore 				TAILQ_REMOVE(&link->hl_txq, pdu, lp_next);
    715        1.1   gdamore 				chan = pdu->lp_chan;
    716        1.1   gdamore 				if (chan != NULL) {
    717        1.1   gdamore 					chan->lc_pending--;
    718        1.1   gdamore 					(*chan->lc_proto->complete)
    719        1.1   gdamore 							(chan->lc_upper, 1);
    720        1.1   gdamore 
    721        1.1   gdamore 					if (chan->lc_pending == 0)
    722        1.1   gdamore 						l2cap_start(chan);
    723        1.1   gdamore 				}
    724        1.1   gdamore 
    725        1.1   gdamore 				pool_put(&l2cap_pdu_pool, pdu);
    726        1.1   gdamore 			}
    727        1.1   gdamore 		} else {
    728        1.1   gdamore 			pdu->lp_pending -= num;
    729        1.1   gdamore 			num = 0;
    730        1.1   gdamore 		}
    731        1.1   gdamore 	}
    732        1.1   gdamore }
    733        1.1   gdamore 
    734        1.1   gdamore /*******************************************************************************
    735        1.1   gdamore  *
    736        1.1   gdamore  *	HCI SCO Connections
    737        1.1   gdamore  */
    738        1.1   gdamore 
    739        1.1   gdamore /*
    740        1.3      tron  * Incoming SCO Connection. We check the list for anybody willing
    741        1.3      tron  * to take it.
    742        1.1   gdamore  */
    743        1.1   gdamore struct hci_link *
    744        1.1   gdamore hci_sco_newconn(struct hci_unit *unit, bdaddr_t *bdaddr)
    745        1.1   gdamore {
    746        1.3      tron 	struct sockaddr_bt laddr, raddr;
    747        1.3      tron 	struct sco_pcb *pcb, *new;
    748        1.3      tron 	struct hci_link *sco, *acl;
    749        1.3      tron 
    750        1.3      tron 	memset(&laddr, 0, sizeof(laddr));
    751        1.3      tron 	laddr.bt_len = sizeof(laddr);
    752        1.3      tron 	laddr.bt_family = AF_BLUETOOTH;
    753        1.3      tron 	bdaddr_copy(&laddr.bt_bdaddr, &unit->hci_bdaddr);
    754        1.3      tron 
    755        1.3      tron 	memset(&raddr, 0, sizeof(raddr));
    756        1.3      tron 	raddr.bt_len = sizeof(raddr);
    757        1.3      tron 	raddr.bt_family = AF_BLUETOOTH;
    758        1.3      tron 	bdaddr_copy(&raddr.bt_bdaddr, bdaddr);
    759        1.3      tron 
    760        1.3      tron 	/*
    761        1.3      tron 	 * There should already be an ACL link up and running before
    762        1.3      tron 	 * the controller sends us SCO connection requests, but you
    763        1.3      tron 	 * never know..
    764        1.3      tron 	 */
    765        1.3      tron 	acl = hci_link_lookup_bdaddr(unit, bdaddr, HCI_LINK_ACL);
    766        1.3      tron 	if (acl == NULL || acl->hl_state != HCI_LINK_OPEN)
    767        1.3      tron 		return NULL;
    768        1.3      tron 
    769        1.3      tron 	LIST_FOREACH(pcb, &sco_pcb, sp_next) {
    770        1.3      tron 		if ((pcb->sp_flags & SP_LISTENING) == 0)
    771        1.3      tron 			continue;
    772        1.3      tron 
    773        1.3      tron 		new = (*pcb->sp_proto->newconn)(pcb->sp_upper, &laddr, &raddr);
    774        1.3      tron 		if (new == NULL)
    775        1.3      tron 			continue;
    776        1.3      tron 
    777        1.3      tron 		/*
    778        1.3      tron 		 * Ok, got new pcb so we can start a new link and fill
    779        1.3      tron 		 * in all the details.
    780        1.3      tron 		 */
    781        1.3      tron 		bdaddr_copy(&new->sp_laddr, &unit->hci_bdaddr);
    782        1.3      tron 		bdaddr_copy(&new->sp_raddr, bdaddr);
    783        1.3      tron 
    784  1.16.10.1   keiichi 		sco = hci_link_alloc(unit, bdaddr, HCI_LINK_SCO);
    785        1.3      tron 		if (sco == NULL) {
    786        1.3      tron 			sco_detach(&new);
    787        1.3      tron 			return NULL;
    788        1.3      tron 		}
    789        1.3      tron 
    790        1.3      tron 		sco->hl_link = hci_acl_open(unit, bdaddr);
    791        1.3      tron 		KASSERT(sco->hl_link == acl);
    792        1.3      tron 
    793        1.3      tron 		sco->hl_sco = new;
    794        1.3      tron 		new->sp_link = sco;
    795        1.3      tron 
    796        1.3      tron 		new->sp_mtu = unit->hci_max_sco_size;
    797        1.3      tron 		return sco;
    798        1.3      tron 	}
    799        1.1   gdamore 
    800        1.1   gdamore 	return NULL;
    801        1.1   gdamore }
    802        1.1   gdamore 
    803        1.1   gdamore /*
    804        1.1   gdamore  * receive SCO packet, we only need to strip the header and send
    805        1.1   gdamore  * it to the right handler
    806        1.1   gdamore  */
    807        1.1   gdamore void
    808        1.1   gdamore hci_sco_recv(struct mbuf *m, struct hci_unit *unit)
    809        1.1   gdamore {
    810        1.1   gdamore 	struct hci_link *link;
    811        1.1   gdamore 	hci_scodata_hdr_t hdr;
    812        1.1   gdamore 	uint16_t handle;
    813        1.1   gdamore 
    814       1.10    plunky 	KASSERT(m != NULL);
    815       1.10    plunky 	KASSERT(unit != NULL);
    816        1.1   gdamore 
    817        1.1   gdamore 	KASSERT(m->m_pkthdr.len >= sizeof(hdr));
    818        1.1   gdamore 	m_copydata(m, 0, sizeof(hdr), &hdr);
    819        1.1   gdamore 	m_adj(m, sizeof(hdr));
    820        1.1   gdamore 
    821        1.1   gdamore #ifdef DIAGNOSTIC
    822        1.1   gdamore 	if (hdr.type != HCI_SCO_DATA_PKT) {
    823       1.16    plunky 		aprint_error_dev(unit->hci_dev, "bad SCO packet type\n");
    824        1.1   gdamore 		goto bad;
    825        1.1   gdamore 	}
    826        1.1   gdamore 
    827        1.1   gdamore 	if (m->m_pkthdr.len != hdr.length) {
    828       1.16    plunky 		aprint_error_dev(unit->hci_dev,
    829       1.16    plunky 		    "bad SCO packet length (%d != %d)\n",
    830       1.16    plunky 		    m->m_pkthdr.len, hdr.length);
    831       1.16    plunky 
    832        1.1   gdamore 		goto bad;
    833        1.1   gdamore 	}
    834        1.1   gdamore #endif
    835        1.1   gdamore 
    836        1.1   gdamore 	hdr.con_handle = le16toh(hdr.con_handle);
    837        1.1   gdamore 	handle = HCI_CON_HANDLE(hdr.con_handle);
    838        1.1   gdamore 
    839        1.1   gdamore 	link = hci_link_lookup_handle(unit, handle);
    840        1.1   gdamore 	if (link == NULL || link->hl_type == HCI_LINK_ACL) {
    841        1.1   gdamore 		DPRINTF("%s: dumping packet for unknown handle #%d\n",
    842       1.16    plunky 			device_xname(unit->hci_dev), handle);
    843        1.1   gdamore 
    844        1.1   gdamore 		goto bad;
    845        1.1   gdamore 	}
    846        1.1   gdamore 
    847        1.1   gdamore 	(*link->hl_sco->sp_proto->input)(link->hl_sco->sp_upper, m);
    848        1.1   gdamore 	return;
    849        1.1   gdamore 
    850        1.1   gdamore bad:
    851        1.1   gdamore 	m_freem(m);
    852        1.1   gdamore }
    853        1.1   gdamore 
    854        1.1   gdamore void
    855        1.8  christos hci_sco_start(struct hci_link *link)
    856        1.1   gdamore {
    857        1.1   gdamore }
    858        1.1   gdamore 
    859        1.1   gdamore /*
    860        1.1   gdamore  * SCO packets have completed at the controller, so we can
    861        1.1   gdamore  * signal up to free the buffer space.
    862        1.1   gdamore  */
    863        1.1   gdamore void
    864        1.1   gdamore hci_sco_complete(struct hci_link *link, int num)
    865        1.1   gdamore {
    866        1.1   gdamore 
    867        1.1   gdamore 	DPRINTFN(5, "handle #%d (num=%d)\n", link->hl_handle, num);
    868        1.1   gdamore 	link->hl_sco->sp_pending--;
    869        1.1   gdamore 	(*link->hl_sco->sp_proto->complete)(link->hl_sco->sp_upper, num);
    870        1.1   gdamore }
    871        1.1   gdamore 
    872        1.1   gdamore /*******************************************************************************
    873        1.1   gdamore  *
    874        1.1   gdamore  *	Generic HCI Connection alloc/free/lookup etc
    875        1.1   gdamore  */
    876        1.1   gdamore 
    877        1.1   gdamore struct hci_link *
    878  1.16.10.1   keiichi hci_link_alloc(struct hci_unit *unit, bdaddr_t *bdaddr, uint8_t type)
    879        1.1   gdamore {
    880        1.1   gdamore 	struct hci_link *link;
    881        1.1   gdamore 
    882       1.10    plunky 	KASSERT(unit != NULL);
    883        1.1   gdamore 
    884        1.1   gdamore 	link = malloc(sizeof(struct hci_link), M_BLUETOOTH, M_NOWAIT | M_ZERO);
    885        1.1   gdamore 	if (link == NULL)
    886        1.1   gdamore 		return NULL;
    887        1.1   gdamore 
    888        1.1   gdamore 	link->hl_unit = unit;
    889  1.16.10.1   keiichi 	link->hl_type = type;
    890        1.1   gdamore 	link->hl_state = HCI_LINK_CLOSED;
    891  1.16.10.1   keiichi 	bdaddr_copy(&link->hl_bdaddr, bdaddr);
    892        1.1   gdamore 
    893        1.1   gdamore 	/* init ACL portion */
    894       1.12        ad 	callout_init(&link->hl_expire, 0);
    895        1.1   gdamore 	callout_setfunc(&link->hl_expire, hci_acl_timeout, link);
    896        1.1   gdamore 
    897        1.1   gdamore 	TAILQ_INIT(&link->hl_txq);	/* outgoing packets */
    898        1.1   gdamore 	TAILQ_INIT(&link->hl_reqs);	/* request queue */
    899        1.1   gdamore 
    900        1.1   gdamore 	link->hl_mtu = L2CAP_MTU_DEFAULT;		/* L2CAP signal mtu */
    901        1.1   gdamore 	link->hl_flush = L2CAP_FLUSH_TIMO_DEFAULT;	/* flush timeout */
    902        1.1   gdamore 
    903        1.1   gdamore 	/* init SCO portion */
    904        1.1   gdamore 	MBUFQ_INIT(&link->hl_data);
    905        1.1   gdamore 
    906        1.1   gdamore 	/* attach to unit */
    907  1.16.10.1   keiichi 	TAILQ_INSERT_TAIL(&unit->hci_links, link, hl_next);
    908        1.1   gdamore 	return link;
    909        1.1   gdamore }
    910        1.1   gdamore 
    911        1.1   gdamore void
    912        1.1   gdamore hci_link_free(struct hci_link *link, int err)
    913        1.1   gdamore {
    914        1.1   gdamore 	struct l2cap_req *req;
    915        1.1   gdamore 	struct l2cap_pdu *pdu;
    916        1.4    plunky 	struct l2cap_channel *chan, *next;
    917        1.1   gdamore 
    918       1.10    plunky 	KASSERT(link != NULL);
    919        1.1   gdamore 
    920        1.1   gdamore 	DPRINTF("#%d, type = %d, state = %d, refcnt = %d\n",
    921        1.1   gdamore 		link->hl_handle, link->hl_type,
    922        1.1   gdamore 		link->hl_state, link->hl_refcnt);
    923        1.1   gdamore 
    924        1.1   gdamore 	/* ACL reference count */
    925        1.1   gdamore 	if (link->hl_refcnt > 0) {
    926        1.4    plunky 		next = LIST_FIRST(&l2cap_active_list);
    927        1.4    plunky 		while ((chan = next) != NULL) {
    928        1.4    plunky 			next = LIST_NEXT(chan, lc_ncid);
    929        1.1   gdamore 			if (chan->lc_link == link)
    930        1.1   gdamore 				l2cap_close(chan, err);
    931        1.1   gdamore 		}
    932        1.1   gdamore 	}
    933        1.1   gdamore 	KASSERT(link->hl_refcnt == 0);
    934        1.1   gdamore 
    935        1.1   gdamore 	/* ACL L2CAP requests.. */
    936        1.1   gdamore 	while ((req = TAILQ_FIRST(&link->hl_reqs)) != NULL)
    937        1.1   gdamore 		l2cap_request_free(req);
    938        1.1   gdamore 
    939        1.1   gdamore 	KASSERT(TAILQ_EMPTY(&link->hl_reqs));
    940        1.1   gdamore 
    941        1.1   gdamore 	/* ACL outgoing data queue */
    942        1.1   gdamore 	while ((pdu = TAILQ_FIRST(&link->hl_txq)) != NULL) {
    943        1.1   gdamore 		TAILQ_REMOVE(&link->hl_txq, pdu, lp_next);
    944        1.1   gdamore 		MBUFQ_DRAIN(&pdu->lp_data);
    945        1.1   gdamore 		if (pdu->lp_pending)
    946        1.1   gdamore 			link->hl_unit->hci_num_acl_pkts += pdu->lp_pending;
    947        1.1   gdamore 
    948        1.1   gdamore 		pool_put(&l2cap_pdu_pool, pdu);
    949        1.1   gdamore 	}
    950        1.1   gdamore 
    951        1.1   gdamore 	KASSERT(TAILQ_EMPTY(&link->hl_txq));
    952        1.1   gdamore 
    953        1.1   gdamore 	/* ACL incoming data packet */
    954        1.1   gdamore 	if (link->hl_rxp != NULL) {
    955        1.1   gdamore 		m_freem(link->hl_rxp);
    956        1.1   gdamore 		link->hl_rxp = NULL;
    957        1.1   gdamore 	}
    958        1.1   gdamore 
    959        1.1   gdamore 	/* SCO master ACL link */
    960        1.1   gdamore 	if (link->hl_link != NULL) {
    961        1.1   gdamore 		hci_acl_close(link->hl_link, err);
    962        1.1   gdamore 		link->hl_link = NULL;
    963        1.1   gdamore 	}
    964        1.1   gdamore 
    965        1.1   gdamore 	/* SCO pcb */
    966        1.1   gdamore 	if (link->hl_sco != NULL) {
    967        1.1   gdamore 		struct sco_pcb *pcb;
    968        1.1   gdamore 
    969        1.1   gdamore 		pcb = link->hl_sco;
    970        1.1   gdamore 		pcb->sp_link = NULL;
    971        1.1   gdamore 		link->hl_sco = NULL;
    972        1.1   gdamore 		(*pcb->sp_proto->disconnected)(pcb->sp_upper, err);
    973        1.1   gdamore 	}
    974        1.1   gdamore 
    975        1.1   gdamore 	/* flush any SCO data */
    976        1.1   gdamore 	MBUFQ_DRAIN(&link->hl_data);
    977        1.1   gdamore 
    978        1.1   gdamore 	/*
    979        1.1   gdamore 	 * Halt the callout - if its already running we cannot free the
    980        1.1   gdamore 	 * link structure but the timeout function will call us back in
    981        1.1   gdamore 	 * any case.
    982        1.1   gdamore 	 */
    983        1.1   gdamore 	link->hl_state = HCI_LINK_CLOSED;
    984        1.1   gdamore 	callout_stop(&link->hl_expire);
    985        1.1   gdamore 	if (callout_invoking(&link->hl_expire))
    986        1.1   gdamore 		return;
    987        1.1   gdamore 
    988       1.15    plunky 	callout_destroy(&link->hl_expire);
    989       1.15    plunky 
    990       1.14    plunky 	/*
    991       1.14    plunky 	 * If we made a note of clock offset, keep it in a memo
    992       1.14    plunky 	 * to facilitate reconnections to this device
    993       1.14    plunky 	 */
    994       1.14    plunky 	if (link->hl_clock != 0) {
    995       1.14    plunky 		struct hci_memo *memo;
    996       1.14    plunky 
    997       1.14    plunky 		memo = hci_memo_new(link->hl_unit, &link->hl_bdaddr);
    998       1.14    plunky 		if (memo != NULL)
    999       1.14    plunky 			memo->clock_offset = link->hl_clock;
   1000       1.14    plunky 	}
   1001       1.14    plunky 
   1002        1.1   gdamore 	TAILQ_REMOVE(&link->hl_unit->hci_links, link, hl_next);
   1003        1.1   gdamore 	free(link, M_BLUETOOTH);
   1004        1.1   gdamore }
   1005        1.1   gdamore 
   1006        1.1   gdamore /*
   1007        1.1   gdamore  * Lookup HCI link by address and type. Note that for SCO links there may
   1008        1.1   gdamore  * be more than one link per address, so we only return links with no
   1009        1.1   gdamore  * handle (ie new links)
   1010        1.1   gdamore  */
   1011        1.1   gdamore struct hci_link *
   1012  1.16.10.1   keiichi hci_link_lookup_bdaddr(struct hci_unit *unit, bdaddr_t *bdaddr, uint8_t type)
   1013        1.1   gdamore {
   1014        1.1   gdamore 	struct hci_link *link;
   1015        1.1   gdamore 
   1016       1.10    plunky 	KASSERT(unit != NULL);
   1017       1.10    plunky 	KASSERT(bdaddr != NULL);
   1018        1.1   gdamore 
   1019        1.1   gdamore 	TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
   1020        1.1   gdamore 		if (link->hl_type != type)
   1021        1.1   gdamore 			continue;
   1022        1.1   gdamore 
   1023        1.1   gdamore 		if (type == HCI_LINK_SCO && link->hl_handle != 0)
   1024        1.1   gdamore 			continue;
   1025        1.1   gdamore 
   1026        1.1   gdamore 		if (bdaddr_same(&link->hl_bdaddr, bdaddr))
   1027        1.1   gdamore 			break;
   1028        1.1   gdamore 	}
   1029        1.1   gdamore 
   1030        1.1   gdamore 	return link;
   1031        1.1   gdamore }
   1032        1.1   gdamore 
   1033        1.1   gdamore struct hci_link *
   1034        1.1   gdamore hci_link_lookup_handle(struct hci_unit *unit, uint16_t handle)
   1035        1.1   gdamore {
   1036        1.1   gdamore 	struct hci_link *link;
   1037        1.1   gdamore 
   1038       1.10    plunky 	KASSERT(unit != NULL);
   1039        1.1   gdamore 
   1040        1.1   gdamore 	TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
   1041        1.1   gdamore 		if (handle == link->hl_handle)
   1042        1.1   gdamore 			break;
   1043        1.1   gdamore 	}
   1044        1.1   gdamore 
   1045        1.1   gdamore 	return link;
   1046        1.1   gdamore }
   1047