1 1.4 msaitoh /* $NetBSD: hci_misc.c,v 1.4 2021/11/22 05:33:57 msaitoh 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.4 msaitoh __KERNEL_RCSID(0, "$NetBSD: hci_misc.c,v 1.4 2021/11/22 05:33:57 msaitoh 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.1 gdamore 47 1.1 gdamore /* 48 1.1 gdamore * cache Inquiry Responses for this number of seconds for routing 49 1.1 gdamore * purposes [sysctl] 50 1.1 gdamore */ 51 1.1 gdamore int hci_memo_expiry = 600; 52 1.1 gdamore 53 1.1 gdamore /* 54 1.1 gdamore * set 'src' address for routing to 'dest' 55 1.1 gdamore */ 56 1.1 gdamore int 57 1.1 gdamore hci_route_lookup(bdaddr_t *src, bdaddr_t *dest) 58 1.1 gdamore { 59 1.1 gdamore struct hci_unit *unit; 60 1.1 gdamore struct hci_link *link; 61 1.1 gdamore struct hci_memo *memo; 62 1.1 gdamore 63 1.1 gdamore /* 64 1.1 gdamore * Walk the ACL connections, if we have a connection 65 1.1 gdamore * to 'dest' already then thats best.. 66 1.1 gdamore */ 67 1.1 gdamore SIMPLEQ_FOREACH(unit, &hci_unit_list, hci_next) { 68 1.1 gdamore if ((unit->hci_flags & BTF_UP) == 0) 69 1.1 gdamore continue; 70 1.1 gdamore 71 1.1 gdamore TAILQ_FOREACH(link, &unit->hci_links, hl_next) { 72 1.1 gdamore if (link->hl_type != HCI_LINK_ACL) 73 1.1 gdamore continue; 74 1.1 gdamore 75 1.1 gdamore if (bdaddr_same(&link->hl_bdaddr, dest)) 76 1.1 gdamore goto found; 77 1.1 gdamore } 78 1.1 gdamore } 79 1.1 gdamore 80 1.1 gdamore /* 81 1.1 gdamore * Now check all the memos to see if there has been an 82 1.4 msaitoh * inquiry response.. 83 1.1 gdamore */ 84 1.1 gdamore SIMPLEQ_FOREACH(unit, &hci_unit_list, hci_next) { 85 1.1 gdamore if ((unit->hci_flags & BTF_UP) == 0) 86 1.1 gdamore continue; 87 1.1 gdamore 88 1.1 gdamore memo = hci_memo_find(unit, dest); 89 1.1 gdamore if (memo) 90 1.1 gdamore goto found; 91 1.1 gdamore } 92 1.1 gdamore 93 1.1 gdamore /* 94 1.1 gdamore * Last ditch effort, lets use the first unit we find 95 1.1 gdamore * thats up and running. (XXX settable default route?) 96 1.1 gdamore */ 97 1.1 gdamore SIMPLEQ_FOREACH(unit, &hci_unit_list, hci_next) { 98 1.1 gdamore if ((unit->hci_flags & BTF_UP) == 0) 99 1.1 gdamore continue; 100 1.1 gdamore 101 1.1 gdamore goto found; 102 1.1 gdamore } 103 1.1 gdamore 104 1.1 gdamore return EHOSTUNREACH; 105 1.1 gdamore 106 1.1 gdamore found: 107 1.1 gdamore bdaddr_copy(src, &unit->hci_bdaddr); 108 1.1 gdamore return 0; 109 1.1 gdamore } 110 1.1 gdamore 111 1.1 gdamore /* 112 1.1 gdamore * find unit memo from bdaddr 113 1.1 gdamore */ 114 1.1 gdamore struct hci_memo * 115 1.1 gdamore hci_memo_find(struct hci_unit *unit, bdaddr_t *bdaddr) 116 1.1 gdamore { 117 1.1 gdamore struct hci_memo *memo, *m0; 118 1.1 gdamore struct timeval now; 119 1.1 gdamore 120 1.1 gdamore microtime(&now); 121 1.1 gdamore 122 1.1 gdamore m0 = LIST_FIRST(&unit->hci_memos); 123 1.1 gdamore while ((memo = m0) != NULL) { 124 1.1 gdamore m0 = LIST_NEXT(memo, next); 125 1.1 gdamore 126 1.1 gdamore if (now.tv_sec > memo->time.tv_sec + hci_memo_expiry) { 127 1.1 gdamore DPRINTF("memo %p too old (expiring)\n", memo); 128 1.1 gdamore hci_memo_free(memo); 129 1.1 gdamore continue; 130 1.1 gdamore } 131 1.1 gdamore 132 1.2 plunky if (bdaddr_same(bdaddr, &memo->bdaddr)) { 133 1.1 gdamore DPRINTF("memo %p found\n", memo); 134 1.1 gdamore return memo; 135 1.1 gdamore } 136 1.1 gdamore } 137 1.1 gdamore 138 1.1 gdamore DPRINTF("no memo found\n"); 139 1.1 gdamore return NULL; 140 1.1 gdamore } 141 1.1 gdamore 142 1.3 plunky /* 143 1.3 plunky * Make a new memo on unit for bdaddr. If a memo exists, just 144 1.3 plunky * update the timestamp. 145 1.3 plunky */ 146 1.3 plunky struct hci_memo * 147 1.3 plunky hci_memo_new(struct hci_unit *unit, bdaddr_t *bdaddr) 148 1.3 plunky { 149 1.3 plunky struct hci_memo *memo; 150 1.3 plunky 151 1.3 plunky memo = hci_memo_find(unit, bdaddr); 152 1.3 plunky if (memo == NULL) { 153 1.3 plunky memo = malloc(sizeof(struct hci_memo), 154 1.3 plunky M_BLUETOOTH, M_NOWAIT | M_ZERO); 155 1.3 plunky 156 1.3 plunky if (memo == NULL) { 157 1.3 plunky DPRINTFN(0, "no memory for memo!\n"); 158 1.3 plunky return NULL; 159 1.3 plunky } 160 1.3 plunky 161 1.3 plunky DPRINTF("memo created for %02x:%02x:%02x:%02x:%02x:%02x\n", 162 1.3 plunky bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], 163 1.3 plunky bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); 164 1.3 plunky 165 1.3 plunky bdaddr_copy(&memo->bdaddr, bdaddr); 166 1.3 plunky LIST_INSERT_HEAD(&unit->hci_memos, memo, next); 167 1.3 plunky } 168 1.3 plunky else 169 1.3 plunky DPRINTF("memo updated for %02x:%02x:%02x:%02x:%02x:%02x\n", 170 1.3 plunky bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], 171 1.3 plunky bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); 172 1.3 plunky 173 1.3 plunky microtime(&memo->time); 174 1.3 plunky return memo; 175 1.3 plunky } 176 1.3 plunky 177 1.1 gdamore void 178 1.1 gdamore hci_memo_free(struct hci_memo *memo) 179 1.1 gdamore { 180 1.1 gdamore 181 1.1 gdamore LIST_REMOVE(memo, next); 182 1.1 gdamore free(memo, M_BLUETOOTH); 183 1.1 gdamore } 184