xref: /dflybsd-src/sys/netbt/hci_misc.c (revision febebf837b1267101987c1c8945f3e9e9e1df7c8)
1*83aacedeSHasso Tepper /* $OpenBSD: src/sys/netbt/hci_misc.c,v 1.2 2008/02/24 21:34:48 uwe Exp $ */
2*83aacedeSHasso Tepper /* $NetBSD: hci_misc.c,v 1.3 2007/09/16 19:59:30 plunky Exp $ */
30a9108ebSHasso Tepper 
40a9108ebSHasso Tepper /*-
50a9108ebSHasso Tepper  * Copyright (c) 2005 Iain Hibbert.
60a9108ebSHasso Tepper  * Copyright (c) 2006 Itronix Inc.
70a9108ebSHasso Tepper  * All rights reserved.
80a9108ebSHasso Tepper  *
90a9108ebSHasso Tepper  * Redistribution and use in source and binary forms, with or without
100a9108ebSHasso Tepper  * modification, are permitted provided that the following conditions
110a9108ebSHasso Tepper  * are met:
120a9108ebSHasso Tepper  * 1. Redistributions of source code must retain the above copyright
130a9108ebSHasso Tepper  *    notice, this list of conditions and the following disclaimer.
140a9108ebSHasso Tepper  * 2. Redistributions in binary form must reproduce the above copyright
150a9108ebSHasso Tepper  *    notice, this list of conditions and the following disclaimer in the
160a9108ebSHasso Tepper  *    documentation and/or other materials provided with the distribution.
170a9108ebSHasso Tepper  * 3. The name of Itronix Inc. may not be used to endorse
180a9108ebSHasso Tepper  *    or promote products derived from this software without specific
190a9108ebSHasso Tepper  *    prior written permission.
200a9108ebSHasso Tepper  *
210a9108ebSHasso Tepper  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
220a9108ebSHasso Tepper  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
230a9108ebSHasso Tepper  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
240a9108ebSHasso Tepper  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
250a9108ebSHasso Tepper  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
260a9108ebSHasso Tepper  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
270a9108ebSHasso Tepper  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
280a9108ebSHasso Tepper  * ON ANY THEORY OF LIABILITY, WHETHER IN
290a9108ebSHasso Tepper  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
300a9108ebSHasso Tepper  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
310a9108ebSHasso Tepper  * POSSIBILITY OF SUCH DAMAGE.
320a9108ebSHasso Tepper  */
330a9108ebSHasso Tepper 
340a9108ebSHasso Tepper #include <sys/param.h>
350a9108ebSHasso Tepper #include <sys/kernel.h>
360a9108ebSHasso Tepper #include <sys/malloc.h>
370a9108ebSHasso Tepper #include <sys/mbuf.h>
380a9108ebSHasso Tepper #include <sys/proc.h>
390a9108ebSHasso Tepper #include <sys/queue.h>
400a9108ebSHasso Tepper #include <sys/systm.h>
410a9108ebSHasso Tepper 
420a9108ebSHasso Tepper #include <netbt/bluetooth.h>
430a9108ebSHasso Tepper #include <netbt/hci.h>
440a9108ebSHasso Tepper 
450a9108ebSHasso Tepper /*
460a9108ebSHasso Tepper  * cache Inquiry Responses for this number of seconds for routing
470a9108ebSHasso Tepper  * purposes [sysctl]
480a9108ebSHasso Tepper  */
490a9108ebSHasso Tepper int hci_memo_expiry = 600;
500a9108ebSHasso Tepper 
510a9108ebSHasso Tepper /*
520a9108ebSHasso Tepper  * set 'src' address for routing to 'dest'
530a9108ebSHasso Tepper  */
540a9108ebSHasso Tepper int
hci_route_lookup(bdaddr_t * src,bdaddr_t * dest)550a9108ebSHasso Tepper hci_route_lookup(bdaddr_t *src, bdaddr_t *dest)
560a9108ebSHasso Tepper {
570a9108ebSHasso Tepper 	struct hci_unit *unit;
580a9108ebSHasso Tepper 	struct hci_link *link;
590a9108ebSHasso Tepper 	struct hci_memo *memo;
600a9108ebSHasso Tepper 
610a9108ebSHasso Tepper 	/*
620a9108ebSHasso Tepper 	 * Walk the ACL connections, if we have a connection
630a9108ebSHasso Tepper 	 * to 'dest' already then thats best..
640a9108ebSHasso Tepper 	 */
650a9108ebSHasso Tepper 	TAILQ_FOREACH(unit, &hci_unit_list, hci_next) {
660a9108ebSHasso Tepper 		if ((unit->hci_flags & BTF_UP) == 0)
670a9108ebSHasso Tepper 			continue;
680a9108ebSHasso Tepper 
690a9108ebSHasso Tepper 		TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
700a9108ebSHasso Tepper 			if (link->hl_type != HCI_LINK_ACL)
710a9108ebSHasso Tepper 				continue;
720a9108ebSHasso Tepper 
730a9108ebSHasso Tepper 			if (bdaddr_same(&link->hl_bdaddr, dest))
740a9108ebSHasso Tepper 				goto found;
750a9108ebSHasso Tepper 		}
760a9108ebSHasso Tepper 	}
770a9108ebSHasso Tepper 
780a9108ebSHasso Tepper 	/*
790a9108ebSHasso Tepper 	 * Now check all the memos to see if there has been an
800a9108ebSHasso Tepper 	 * inquiry repsonse..
810a9108ebSHasso Tepper 	 */
820a9108ebSHasso Tepper 	TAILQ_FOREACH(unit, &hci_unit_list, hci_next) {
830a9108ebSHasso Tepper 		if ((unit->hci_flags & BTF_UP) == 0)
840a9108ebSHasso Tepper 			continue;
850a9108ebSHasso Tepper 
860a9108ebSHasso Tepper 		memo = hci_memo_find(unit, dest);
870a9108ebSHasso Tepper 		if (memo)
880a9108ebSHasso Tepper 			goto found;
890a9108ebSHasso Tepper 	}
900a9108ebSHasso Tepper 
910a9108ebSHasso Tepper 	/*
920a9108ebSHasso Tepper 	 * Last ditch effort, lets use the first unit we find
930a9108ebSHasso Tepper 	 * thats up and running. (XXX settable default route?)
940a9108ebSHasso Tepper 	 */
950a9108ebSHasso Tepper 	TAILQ_FOREACH(unit, &hci_unit_list, hci_next) {
960a9108ebSHasso Tepper 		if ((unit->hci_flags & BTF_UP) == 0)
970a9108ebSHasso Tepper 			continue;
980a9108ebSHasso Tepper 
990a9108ebSHasso Tepper 		goto found;
1000a9108ebSHasso Tepper 	}
1010a9108ebSHasso Tepper 
1020a9108ebSHasso Tepper 	return EHOSTUNREACH;
1030a9108ebSHasso Tepper 
1040a9108ebSHasso Tepper found:
1050a9108ebSHasso Tepper 	bdaddr_copy(src, &unit->hci_bdaddr);
1060a9108ebSHasso Tepper 	return 0;
1070a9108ebSHasso Tepper }
1080a9108ebSHasso Tepper 
1090a9108ebSHasso Tepper /*
1100a9108ebSHasso Tepper  * find unit memo from bdaddr
1110a9108ebSHasso Tepper  */
1120a9108ebSHasso Tepper struct hci_memo *
hci_memo_find(struct hci_unit * unit,bdaddr_t * bdaddr)1130a9108ebSHasso Tepper hci_memo_find(struct hci_unit *unit, bdaddr_t *bdaddr)
1140a9108ebSHasso Tepper {
1150a9108ebSHasso Tepper 	struct hci_memo *memo, *m0;
1160a9108ebSHasso Tepper 	struct timeval now;
1170a9108ebSHasso Tepper 
1180a9108ebSHasso Tepper 	microtime(&now);
1190a9108ebSHasso Tepper 
1200a9108ebSHasso Tepper 	m0 = LIST_FIRST(&unit->hci_memos);
1210a9108ebSHasso Tepper 	while ((memo = m0) != NULL) {
1220a9108ebSHasso Tepper 		m0 = LIST_NEXT(memo, next);
1230a9108ebSHasso Tepper 
1240a9108ebSHasso Tepper 		if (now.tv_sec > memo->time.tv_sec + hci_memo_expiry) {
1250a9108ebSHasso Tepper 			DPRINTF("memo %p too old (expiring)\n", memo);
1260a9108ebSHasso Tepper 			hci_memo_free(memo);
1270a9108ebSHasso Tepper 			continue;
1280a9108ebSHasso Tepper 		}
1290a9108ebSHasso Tepper 
130*83aacedeSHasso Tepper 		if (bdaddr_same(bdaddr, &memo->bdaddr)) {
1310a9108ebSHasso Tepper 			DPRINTF("memo %p found\n", memo);
1320a9108ebSHasso Tepper 			return memo;
1330a9108ebSHasso Tepper 		}
1340a9108ebSHasso Tepper 	}
1350a9108ebSHasso Tepper 
1360a9108ebSHasso Tepper 	DPRINTF("no memo found\n");
1370a9108ebSHasso Tepper 	return NULL;
1380a9108ebSHasso Tepper }
1390a9108ebSHasso Tepper 
140*83aacedeSHasso Tepper /*
141*83aacedeSHasso Tepper  * Make a new memo on unit for bdaddr. If a memo exists, just
142*83aacedeSHasso Tepper  * update the timestamp.
143*83aacedeSHasso Tepper  */
144*83aacedeSHasso Tepper struct hci_memo *
hci_memo_new(struct hci_unit * unit,bdaddr_t * bdaddr)145*83aacedeSHasso Tepper hci_memo_new(struct hci_unit *unit, bdaddr_t *bdaddr)
146*83aacedeSHasso Tepper {
147*83aacedeSHasso Tepper 	struct hci_memo *memo;
148*83aacedeSHasso Tepper 
149*83aacedeSHasso Tepper 	memo = hci_memo_find(unit, bdaddr);
150*83aacedeSHasso Tepper 	if (memo == NULL) {
151*83aacedeSHasso Tepper 		memo = kmalloc(sizeof(struct hci_memo),
152*83aacedeSHasso Tepper 			M_BLUETOOTH, M_NOWAIT | M_ZERO);
153*83aacedeSHasso Tepper 
154*83aacedeSHasso Tepper 		if (memo == NULL) {
155*83aacedeSHasso Tepper 			DPRINTFN(0, "no memory for memo!\n");
156*83aacedeSHasso Tepper 			return NULL;
157*83aacedeSHasso Tepper 		}
158*83aacedeSHasso Tepper 
159*83aacedeSHasso Tepper 		DPRINTF("memo created for %02x:%02x:%02x:%02x:%02x:%02x\n",
160*83aacedeSHasso Tepper 			bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
161*83aacedeSHasso Tepper 			bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]);
162*83aacedeSHasso Tepper 
163*83aacedeSHasso Tepper 		bdaddr_copy(&memo->bdaddr, bdaddr);
164*83aacedeSHasso Tepper 		LIST_INSERT_HEAD(&unit->hci_memos, memo, next);
165*83aacedeSHasso Tepper 	}
166*83aacedeSHasso Tepper 	else
167*83aacedeSHasso Tepper 		DPRINTF("memo updated for %02x:%02x:%02x:%02x:%02x:%02x\n",
168*83aacedeSHasso Tepper 			bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
169*83aacedeSHasso Tepper 			bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]);
170*83aacedeSHasso Tepper 
171*83aacedeSHasso Tepper 	microtime(&memo->time);
172*83aacedeSHasso Tepper 	return memo;
173*83aacedeSHasso Tepper }
174*83aacedeSHasso Tepper 
1750a9108ebSHasso Tepper void
hci_memo_free(struct hci_memo * memo)1760a9108ebSHasso Tepper hci_memo_free(struct hci_memo *memo)
1770a9108ebSHasso Tepper {
1780a9108ebSHasso Tepper 
1790a9108ebSHasso Tepper 	LIST_REMOVE(memo, next);
1800a9108ebSHasso Tepper 	kfree(memo, M_BLUETOOTH);
1810a9108ebSHasso Tepper }
182